diff options
1132 files changed, 20859 insertions, 10416 deletions
diff --git a/AconfigFlags.bp b/AconfigFlags.bp index 7a1add3eb57e..6b8baf8723c1 100644 --- a/AconfigFlags.bp +++ b/AconfigFlags.bp @@ -99,6 +99,7 @@ aconfig_declarations_group { "framework_graphics_flags_java_lib", "hwui_flags_java_lib", "libcore_exported_aconfig_flags_lib", + "libgui_flags_java_lib", "power_flags_lib", "sdk_sandbox_flags_lib", "surfaceflinger_flags_java_lib", @@ -1208,6 +1209,12 @@ java_aconfig_library { defaults: ["framework-minus-apex-aconfig-java-defaults"], } +java_aconfig_library { + name: "libgui_flags_java_lib", + aconfig_declarations: "libgui_flags", + defaults: ["framework-minus-apex-aconfig-java-defaults"], +} + // Content Capture aconfig_declarations { name: "android.view.contentcapture.flags-aconfig", diff --git a/Android.bp b/Android.bp index 6fa66506cbe6..7f4871f5032a 100644 --- a/Android.bp +++ b/Android.bp @@ -401,6 +401,7 @@ java_defaults { ], sdk_version: "core_platform", static_libs: [ + "aconfig_storage_reader_java", "android.hardware.common.fmq-V1-java", "bouncycastle-repackaged-unbundled", "com.android.sysprop.foldlockbehavior", diff --git a/apex/jobscheduler/service/java/com/android/server/alarm/AlarmManagerService.java b/apex/jobscheduler/service/java/com/android/server/alarm/AlarmManagerService.java index 857154fee453..9a178e573b53 100644 --- a/apex/jobscheduler/service/java/com/android/server/alarm/AlarmManagerService.java +++ b/apex/jobscheduler/service/java/com/android/server/alarm/AlarmManagerService.java @@ -4495,8 +4495,9 @@ public class AlarmManagerService extends SystemService { final int[] userIds = mUserWakeupStore.getUserIdsToWakeup(nowELAPSED); for (int i = 0; i < userIds.length; i++) { - if (!mActivityManagerInternal.startUserInBackground( - userIds[i])) { + if (mActivityManagerInternal.isUserRunning(userIds[i], 0) + || !mActivityManagerInternal.startUserInBackground( + userIds[i])) { mUserWakeupStore.removeUserWakeup(userIds[i]); } } diff --git a/apex/jobscheduler/service/java/com/android/server/usage/AppStandbyController.java b/apex/jobscheduler/service/java/com/android/server/usage/AppStandbyController.java index c3fe0314636e..d92351de3aa1 100644 --- a/apex/jobscheduler/service/java/com/android/server/usage/AppStandbyController.java +++ b/apex/jobscheduler/service/java/com/android/server/usage/AppStandbyController.java @@ -1990,7 +1990,7 @@ public class AppStandbyController } } if (android.app.admin.flags.Flags.disallowUserControlBgUsageFix()) { - if (!Flags.avoidIdleCheck()) { + if (!Flags.avoidIdleCheck() || mInjector.getBootPhase() >= PHASE_BOOT_COMPLETED) { postCheckIdleStates(userId); } } diff --git a/core/api/current.txt b/core/api/current.txt index 69c409bb5261..c5a70df0905e 100644 --- a/core/api/current.txt +++ b/core/api/current.txt @@ -34161,6 +34161,7 @@ package android.os { field public static final int USAGE_CLASS_UNKNOWN = 0; // 0x0 field public static final int USAGE_COMMUNICATION_REQUEST = 65; // 0x41 field public static final int USAGE_HARDWARE_FEEDBACK = 50; // 0x32 + field @FlaggedApi("android.os.vibrator.vibration_attribute_ime_usage_api") public static final int USAGE_IME_FEEDBACK = 82; // 0x52 field public static final int USAGE_MEDIA = 19; // 0x13 field public static final int USAGE_NOTIFICATION = 49; // 0x31 field public static final int USAGE_PHYSICAL_EMULATION = 34; // 0x22 @@ -54862,8 +54863,6 @@ package android.view.accessibility { method @Deprecated public void addAction(int); method public void addChild(android.view.View); method public void addChild(android.view.View, int); - method @FlaggedApi("android.view.accessibility.support_multiple_labeledby") public void addLabeledBy(@NonNull android.view.View); - method @FlaggedApi("android.view.accessibility.support_multiple_labeledby") public void addLabeledBy(@NonNull android.view.View, int); method public boolean canOpenPopup(); method public int describeContents(); method public java.util.List<android.view.accessibility.AccessibilityNodeInfo> findAccessibilityNodeInfosByText(String); @@ -54892,7 +54891,6 @@ package android.view.accessibility { method public int getInputType(); method public android.view.accessibility.AccessibilityNodeInfo getLabelFor(); method public android.view.accessibility.AccessibilityNodeInfo getLabeledBy(); - method @FlaggedApi("android.view.accessibility.support_multiple_labeledby") @NonNull public java.util.List<android.view.accessibility.AccessibilityNodeInfo> getLabeledByList(); method public int getLiveRegion(); method public int getMaxTextLength(); method @NonNull public java.time.Duration getMinDurationBetweenContentChanges(); @@ -54953,8 +54951,6 @@ package android.view.accessibility { method public boolean removeAction(android.view.accessibility.AccessibilityNodeInfo.AccessibilityAction); method public boolean removeChild(android.view.View); method public boolean removeChild(android.view.View, int); - method @FlaggedApi("android.view.accessibility.support_multiple_labeledby") public boolean removeLabeledBy(@NonNull android.view.View); - method @FlaggedApi("android.view.accessibility.support_multiple_labeledby") public boolean removeLabeledBy(@NonNull android.view.View, int); method public void setAccessibilityDataSensitive(boolean); method public void setAccessibilityFocused(boolean); method public void setAvailableExtraData(java.util.List<java.lang.String>); diff --git a/core/java/android/app/ActivityClient.java b/core/java/android/app/ActivityClient.java index 10dc3c6c1360..62aa5e01c1e5 100644 --- a/core/java/android/app/ActivityClient.java +++ b/core/java/android/app/ActivityClient.java @@ -25,7 +25,6 @@ import android.content.ComponentName; import android.content.ContentProvider; import android.content.Intent; import android.content.res.Configuration; -import android.content.res.Resources; import android.net.Uri; import android.os.Bundle; import android.os.IBinder; @@ -660,28 +659,6 @@ public class ActivityClient { } } - /** - * Shows or hides a Camera app compat toggle for stretched issues with the requested state. - * - * @param token The token for the window that needs a control. - * @param showControl Whether the control should be shown or hidden. - * @param transformationApplied Whether the treatment is already applied. - * @param callback The callback executed when the user clicks on a control. - */ - void requestCompatCameraControl(Resources res, IBinder token, boolean showControl, - boolean transformationApplied, ICompatCameraControlCallback callback) { - if (!res.getBoolean(com.android.internal.R.bool - .config_isCameraCompatControlForStretchedIssuesEnabled)) { - return; - } - try { - getActivityClientController().requestCompatCameraControl( - token, showControl, transformationApplied, callback); - } catch (RemoteException e) { - e.rethrowFromSystemServer(); - } - } - public static ActivityClient getInstance() { return sInstance.get(); } diff --git a/core/java/android/app/ActivityTaskManager.java b/core/java/android/app/ActivityTaskManager.java index c8ab260c8c4e..799df1f9227a 100644 --- a/core/java/android/app/ActivityTaskManager.java +++ b/core/java/android/app/ActivityTaskManager.java @@ -172,7 +172,7 @@ public class ActivityTaskManager { } } - /** Removes root tasks of the activity types from the system. */ + /** Removes root tasks of the activity types from the Default TDA of all displays. */ @RequiresPermission(android.Manifest.permission.MANAGE_ACTIVITY_TASKS) public void removeRootTasksWithActivityTypes(@NonNull int[] activityTypes) { try { diff --git a/core/java/android/app/ActivityThread.java b/core/java/android/app/ActivityThread.java index 75aab7d0fc63..07e4f2203cf5 100644 --- a/core/java/android/app/ActivityThread.java +++ b/core/java/android/app/ActivityThread.java @@ -734,19 +734,6 @@ public final class ActivityThread extends ClientTransactionHandler activityWindowInfo, false /* alwaysReportChange */); } - - @Override - public void requestCompatCameraControl(boolean showControl, - boolean transformationApplied, ICompatCameraControlCallback callback) { - if (activity == null) { - throw new IllegalStateException( - "Received camera compat control update for non-existing activity"); - } - ActivityClient.getInstance().requestCompatCameraControl( - activity.getResources(), token, showControl, transformationApplied, - callback); - } - }; } diff --git a/core/java/android/app/AppCompatTaskInfo.java b/core/java/android/app/AppCompatTaskInfo.java index 92543b1c7646..b03011fdb90c 100644 --- a/core/java/android/app/AppCompatTaskInfo.java +++ b/core/java/android/app/AppCompatTaskInfo.java @@ -136,8 +136,7 @@ public class AppCompatTaskInfo implements Parcelable { * @return {@value true} if the task has some compat ui. */ public boolean hasCompatUI() { - return cameraCompatTaskInfo.hasCameraCompatUI() || topActivityInSizeCompat - || topActivityEligibleForLetterboxEducation + return topActivityInSizeCompat || topActivityEligibleForLetterboxEducation || isLetterboxDoubleTapEnabled || topActivityEligibleForUserAspectRatioButton; } diff --git a/core/java/android/app/CameraCompatTaskInfo.java b/core/java/android/app/CameraCompatTaskInfo.java index 1e116b7a759c..53eddbee6b03 100644 --- a/core/java/android/app/CameraCompatTaskInfo.java +++ b/core/java/android/app/CameraCompatTaskInfo.java @@ -31,45 +31,6 @@ import java.lang.annotation.RetentionPolicy; */ public class CameraCompatTaskInfo implements Parcelable { /** - * Camera compat control isn't shown because it's not requested by heuristics. - */ - public static final int CAMERA_COMPAT_CONTROL_HIDDEN = 0; - - /** - * Camera compat control is shown with the treatment suggested. - */ - public static final int CAMERA_COMPAT_CONTROL_TREATMENT_SUGGESTED = 1; - - /** - * Camera compat control is shown to allow reverting the applied treatment. - */ - public static final int CAMERA_COMPAT_CONTROL_TREATMENT_APPLIED = 2; - - /** - * Camera compat control is dismissed by user. - */ - public static final int CAMERA_COMPAT_CONTROL_DISMISSED = 3; - - /** - * Enum for the Camera app compat control states. - */ - @Retention(RetentionPolicy.SOURCE) - @IntDef(prefix = { "CAMERA_COMPAT_CONTROL_" }, value = { - CAMERA_COMPAT_CONTROL_HIDDEN, - CAMERA_COMPAT_CONTROL_TREATMENT_SUGGESTED, - CAMERA_COMPAT_CONTROL_TREATMENT_APPLIED, - CAMERA_COMPAT_CONTROL_DISMISSED, - }) - public @interface CameraCompatControlState {} - - /** - * State of the Camera app compat control which is used to correct stretched viewfinder - * in apps that don't handle all possible configurations and changes between them correctly. - */ - @CameraCompatControlState - public int cameraCompatControlState = CAMERA_COMPAT_CONTROL_HIDDEN; - - /** * The value to use when no camera compat treatment should be applied to a windowed task. */ public static final int CAMERA_COMPAT_FREEFORM_NONE = 0; @@ -137,7 +98,6 @@ public class CameraCompatTaskInfo implements Parcelable { * Reads the CameraCompatTaskInfo from a parcel. */ void readFromParcel(Parcel source) { - cameraCompatControlState = source.readInt(); freeformCameraCompatMode = source.readInt(); } @@ -146,26 +106,10 @@ public class CameraCompatTaskInfo implements Parcelable { */ @Override public void writeToParcel(Parcel dest, int flags) { - dest.writeInt(cameraCompatControlState); dest.writeInt(freeformCameraCompatMode); } /** - * @return {@value true} if the task has camera compat controls. - */ - public boolean hasCameraCompatControl() { - return cameraCompatControlState != CAMERA_COMPAT_CONTROL_HIDDEN - && cameraCompatControlState != CAMERA_COMPAT_CONTROL_DISMISSED; - } - - /** - * @return {@value true} if the task has some compat ui. - */ - public boolean hasCameraCompatUI() { - return hasCameraCompatControl(); - } - - /** * @return {@code true} if the camera compat parameters that are important for task organizers * are equal. */ @@ -183,33 +127,16 @@ public class CameraCompatTaskInfo implements Parcelable { if (that == null) { return false; } - return cameraCompatControlState == that.cameraCompatControlState - && freeformCameraCompatMode == that.freeformCameraCompatMode; + return freeformCameraCompatMode == that.freeformCameraCompatMode; } @Override public String toString() { - return "CameraCompatTaskInfo { cameraCompatControlState=" - + cameraCompatControlStateToString(cameraCompatControlState) - + " freeformCameraCompatMode=" + return "CameraCompatTaskInfo { freeformCameraCompatMode=" + freeformCameraCompatModeToString(freeformCameraCompatMode) + "}"; } - /** Human readable version of the camera control state. */ - @NonNull - public static String cameraCompatControlStateToString( - @CameraCompatControlState int cameraCompatControlState) { - return switch (cameraCompatControlState) { - case CAMERA_COMPAT_CONTROL_HIDDEN -> "hidden"; - case CAMERA_COMPAT_CONTROL_TREATMENT_SUGGESTED -> "treatment-suggested"; - case CAMERA_COMPAT_CONTROL_TREATMENT_APPLIED -> "treatment-applied"; - case CAMERA_COMPAT_CONTROL_DISMISSED -> "dismissed"; - default -> throw new AssertionError( - "Unexpected camera compat control state: " + cameraCompatControlState); - }; - } - /** Human readable version of the freeform camera compat mode. */ @NonNull public static String freeformCameraCompatModeToString( diff --git a/core/java/android/app/IActivityClientController.aidl b/core/java/android/app/IActivityClientController.aidl index 9c8fea15c712..961501503348 100644 --- a/core/java/android/app/IActivityClientController.aidl +++ b/core/java/android/app/IActivityClientController.aidl @@ -17,7 +17,6 @@ package android.app; import android.app.ActivityManager; -import android.app.ICompatCameraControlCallback; import android.app.IRequestFinishCallback; import android.app.PictureInPictureParams; import android.content.ComponentName; @@ -172,17 +171,6 @@ interface IActivityClientController { oneway void splashScreenAttached(in IBinder token); /** - * Shows or hides a Camera app compat toggle for stretched issues with the requested state. - * - * @param token The token for the window that needs a control. - * @param showControl Whether the control should be shown or hidden. - * @param transformationApplied Whether the treatment is already applied. - * @param callback The callback executed when the user clicks on a control. - */ - oneway void requestCompatCameraControl(in IBinder token, boolean showControl, - boolean transformationApplied, in ICompatCameraControlCallback callback); - - /** * If set, any activity launch in the same task will be overridden to the locale of activity * that started the task. */ diff --git a/core/java/android/app/Person.java b/core/java/android/app/Person.java index 96f6f4eac372..c7432c571e43 100644 --- a/core/java/android/app/Person.java +++ b/core/java/android/app/Person.java @@ -189,10 +189,8 @@ public final class Person implements Parcelable { */ public void visitUris(@NonNull Consumer<Uri> visitor) { visitor.accept(getIconUri()); - if (Flags.visitPersonUri()) { - if (mUri != null && !mUri.isEmpty()) { - visitor.accept(Uri.parse(mUri)); - } + if (mUri != null && !mUri.isEmpty()) { + visitor.accept(Uri.parse(mUri)); } } diff --git a/core/java/android/app/TaskInfo.java b/core/java/android/app/TaskInfo.java index 531537c374ce..c83dd65233de 100644 --- a/core/java/android/app/TaskInfo.java +++ b/core/java/android/app/TaskInfo.java @@ -304,6 +304,12 @@ public class TaskInfo { public boolean isTopActivityStyleFloating; /** + * The last non-fullscreen bounds the task was launched in or resized to. + * @hide + */ + public Rect lastNonFullscreenBounds; + + /** * The URI of the intent that generated the top-most activity opened using a URL. * @hide */ @@ -450,6 +456,7 @@ public class TaskInfo { && Objects.equals(topActivity, that.topActivity) && isTopActivityTransparent == that.isTopActivityTransparent && isTopActivityStyleFloating == that.isTopActivityStyleFloating + && lastNonFullscreenBounds == this.lastNonFullscreenBounds && Objects.equals(capturedLink, that.capturedLink) && capturedLinkTimestamp == that.capturedLinkTimestamp && appCompatTaskInfo.equalsForTaskOrganizer(that.appCompatTaskInfo); @@ -522,6 +529,7 @@ public class TaskInfo { displayAreaFeatureId = source.readInt(); isTopActivityTransparent = source.readBoolean(); isTopActivityStyleFloating = source.readBoolean(); + lastNonFullscreenBounds = source.readTypedObject(Rect.CREATOR); capturedLink = source.readTypedObject(Uri.CREATOR); capturedLinkTimestamp = source.readLong(); appCompatTaskInfo = source.readTypedObject(AppCompatTaskInfo.CREATOR); @@ -572,6 +580,7 @@ public class TaskInfo { dest.writeInt(displayAreaFeatureId); dest.writeBoolean(isTopActivityTransparent); dest.writeBoolean(isTopActivityStyleFloating); + dest.writeTypedObject(lastNonFullscreenBounds, flags); dest.writeTypedObject(capturedLink, flags); dest.writeLong(capturedLinkTimestamp); dest.writeTypedObject(appCompatTaskInfo, flags); @@ -612,6 +621,7 @@ public class TaskInfo { + " displayAreaFeatureId=" + displayAreaFeatureId + " isTopActivityTransparent=" + isTopActivityTransparent + " isTopActivityStyleFloating=" + isTopActivityStyleFloating + + " lastNonFullscreenBounds=" + lastNonFullscreenBounds + " capturedLink=" + capturedLink + " capturedLinkTimestamp=" + capturedLinkTimestamp + " appCompatTaskInfo=" + appCompatTaskInfo diff --git a/core/java/android/companion/virtual/flags/flags.aconfig b/core/java/android/companion/virtual/flags/flags.aconfig index 55278f617ba9..a1ae9da636d5 100644 --- a/core/java/android/companion/virtual/flags/flags.aconfig +++ b/core/java/android/companion/virtual/flags/flags.aconfig @@ -84,6 +84,13 @@ flag { } flag { + namespace: "virtual_devices" + name: "enforce_remote_device_opt_out_on_all_virtual_displays" + description: "Respect canDisplayOnRemoteDevices on all virtual displays" + bug: "338973239" +} + +flag { namespace: "virtual_devices" name: "virtual_display_multi_window_mode_support" description: "Add support for WINDOWING_MODE_MULTI_WINDOW to virtual displays by default" @@ -117,3 +124,11 @@ flag { description: "Enable high resolution scroll" bug: "335160780" } + +flag { + name: "camera_multiple_input_streams" + is_exported: true + namespace: "virtual_devices" + description: "Expose multiple surface for the virtual camera owner for different stream resolution" + bug: "341083465" +} diff --git a/core/java/android/content/IntentSender.java b/core/java/android/content/IntentSender.java index 32d1964dd4f0..ca6d86ae2dd8 100644 --- a/core/java/android/content/IntentSender.java +++ b/core/java/android/content/IntentSender.java @@ -16,6 +16,8 @@ package android.content; +import static android.os.Build.VERSION_CODES.VANILLA_ICE_CREAM; + import android.annotation.FlaggedApi; import android.annotation.Nullable; import android.app.ActivityManager; @@ -23,6 +25,9 @@ import android.app.ActivityManager.PendingIntentInfo; import android.app.ActivityOptions; import android.app.ActivityThread; import android.app.IApplicationThread; +import android.app.compat.CompatChanges; +import android.compat.annotation.ChangeId; +import android.compat.annotation.EnabledAfter; import android.compat.annotation.UnsupportedAppUsage; import android.os.Bundle; import android.os.Handler; @@ -65,6 +70,11 @@ import java.util.concurrent.Executor; * {@link android.app.PendingIntent#getIntentSender() PendingIntent.getIntentSender()}. */ public class IntentSender implements Parcelable { + /** If enabled consider the deprecated @hide method as removed. */ + @ChangeId + @EnabledAfter(targetSdkVersion = VANILLA_ICE_CREAM) + private static final long REMOVE_HIDDEN_SEND_INTENT_METHOD = 356174596; + private static final Bundle SEND_INTENT_DEFAULT_OPTIONS = ActivityOptions.makeBasic().setPendingIntentBackgroundActivityStartMode( ActivityOptions.MODE_BACKGROUND_ACTIVITY_START_COMPAT).toBundle(); @@ -220,6 +230,44 @@ public class IntentSender implements Parcelable { * original Intent. Use {@code null} to not modify the original Intent. * @param onFinished The object to call back on when the send has * completed, or {@code null} for no callback. + * @param handler Handler identifying the thread on which the callback + * should happen. If {@code null}, the callback will happen from the thread + * pool of the process. + * @param options Additional options the caller would like to provide to modify the sending + * behavior. Typically built from using {@link ActivityOptions} to apply to an activity start. + * + * @throws SendIntentException Throws CanceledIntentException if the IntentSender + * is no longer allowing more intents to be sent through it. + * + * @deprecated use {@link #sendIntent(Context, int, Intent, String, Bundle, Executor, + * OnFinished)} + * + * @hide + */ + @Deprecated public void sendIntent(Context context, int code, Intent intent, + OnFinished onFinished, Handler handler, String requiredPermission, + @Nullable Bundle options) + throws SendIntentException { + if (CompatChanges.isChangeEnabled(REMOVE_HIDDEN_SEND_INTENT_METHOD)) { + throw new NoSuchMethodError("This overload of sendIntent was removed."); + } + sendIntent(context, code, intent, requiredPermission, options, + handler == null ? null : handler::post, onFinished); + } + + /** + * Perform the operation associated with this IntentSender, allowing the + * caller to specify information about the Intent to use and be notified + * when the send has completed. + * + * @param context The Context of the caller. This may be {@code null} if + * <var>intent</var> is also {@code null}. + * @param code Result code to supply back to the IntentSender's target. + * @param intent Additional Intent data. See {@link Intent#fillIn + * Intent.fillIn()} for information on how this is applied to the + * original Intent. Use {@code null} to not modify the original Intent. + * @param onFinished The object to call back on when the send has + * completed, or {@code null} for no callback. * @param executor Executor identifying the thread on which the callback * should happen. If {@code null}, the callback will happen from the thread * pool of the process. diff --git a/core/java/android/content/pm/ActivityInfo.java b/core/java/android/content/pm/ActivityInfo.java index 6952a09f2d90..481e6b530162 100644 --- a/core/java/android/content/pm/ActivityInfo.java +++ b/core/java/android/content/pm/ActivityInfo.java @@ -617,7 +617,7 @@ public class ActivityInfo extends ComponentInfo implements Parcelable { */ public static final int FLAG_ENABLE_VR_MODE = 0x8000; /** - * Bit in {@link #flags} indicating if the activity can be displayed on a remote device. + * Bit in {@link #flags} indicating if the activity can be displayed on a virtual display. * Corresponds to {@link android.R.attr#canDisplayOnRemoteDevices} * @hide */ diff --git a/core/java/android/content/pm/multiuser.aconfig b/core/java/android/content/pm/multiuser.aconfig index 88fbbddd28c9..77f2323884ca 100644 --- a/core/java/android/content/pm/multiuser.aconfig +++ b/core/java/android/content/pm/multiuser.aconfig @@ -171,6 +171,16 @@ flag { } flag { + name: "fix_disabling_of_mu_toggle_when_restriction_applied" + namespace: "multiuser" + description: "When no_user_switch is set but no EnforcedAdmin is present, the toggle has to be disabled" + bug: "356387759" + metadata { + purpose: PURPOSE_BUGFIX + } +} + +flag { name: "cache_quiet_mode_state" namespace: "multiuser" description: "Optimise quiet mode state retrieval" @@ -359,3 +369,13 @@ flag { purpose: PURPOSE_BUGFIX } } + +flag { + name: "show_different_creation_error_for_unsupported_devices" + namespace: "profile_experiences" + description: "On private space create error due to child account added/fully managed user show message with link to the Help Center to find out more." + bug: "340130375" + metadata { + purpose: PURPOSE_BUGFIX + } +} diff --git a/core/java/android/hardware/devicestate/feature/flags.aconfig b/core/java/android/hardware/devicestate/feature/flags.aconfig index a09c84dcedcb..98ba9192044d 100644 --- a/core/java/android/hardware/devicestate/feature/flags.aconfig +++ b/core/java/android/hardware/devicestate/feature/flags.aconfig @@ -17,4 +17,16 @@ flag { description: "Client migration to updated DeviceStateManager API's" bug: "336640888" is_fixed_read_only: true +} + +flag { + name: "device_state_requester_cancel_state" + is_exported: true + namespace: "windowing_sdk" + description: "Removes foreground requirement if process attempting to cancel a state request is the requester" + bug: "354772125" + is_fixed_read_only: true + metadata { + purpose: PURPOSE_BUGFIX + } }
\ No newline at end of file diff --git a/core/java/android/inputmethodservice/InputMethodService.java b/core/java/android/inputmethodservice/InputMethodService.java index fe14d4570e9e..00ce9491784b 100644 --- a/core/java/android/inputmethodservice/InputMethodService.java +++ b/core/java/android/inputmethodservice/InputMethodService.java @@ -1171,12 +1171,14 @@ public class InputMethodService extends AbstractInputMethodService { } switch (motionEvent.getAction()) { case MotionEvent.ACTION_DOWN: + case MotionEvent.ACTION_HOVER_ENTER: // Consume and ignore all touches while stylus is down to prevent // accidental touches from going to the app while writing. mPrivOps.setHandwritingSurfaceNotTouchable(false); break; case MotionEvent.ACTION_UP: case MotionEvent.ACTION_CANCEL: + case MotionEvent.ACTION_HOVER_EXIT: // Go back to only consuming stylus events so that the user // can continue to interact with the app using touch // when the stylus is not down. diff --git a/core/java/android/os/BatteryConsumer.java b/core/java/android/os/BatteryConsumer.java index 000a537cf3c3..623196b637f6 100644 --- a/core/java/android/os/BatteryConsumer.java +++ b/core/java/android/os/BatteryConsumer.java @@ -209,7 +209,8 @@ public abstract class BatteryConsumer { POWER_COMPONENT_VIDEO, POWER_COMPONENT_FLASHLIGHT, POWER_COMPONENT_CAMERA, - POWER_COMPONENT_GNSS}; + POWER_COMPONENT_GNSS, + POWER_COMPONENT_SENSORS}; Arrays.sort(supportedPowerComponents); SUPPORTED_POWER_COMPONENTS_PER_PROCESS_STATE = IntArray.wrap(supportedPowerComponents); }; diff --git a/core/java/android/os/BatteryStats.java b/core/java/android/os/BatteryStats.java index cdffea4e9ede..c7751e3e5cea 100644 --- a/core/java/android/os/BatteryStats.java +++ b/core/java/android/os/BatteryStats.java @@ -3077,7 +3077,7 @@ public abstract class BatteryStats { public static final String[] HISTORY_EVENT_NAMES = new String[] { "null", "proc", "fg", "top", "sync", "wake_lock_in", "job", "user", "userfg", "conn", "active", "pkginst", "pkgunin", "alarm", "stats", "pkginactive", "pkgactive", - "tmpwhitelist", "screenwake", "wakeupap", "longwake", "est_capacity", "state" + "tmpwhitelist", "screenwake", "wakeupap", "longwake", "state" }; public static final String[] HISTORY_EVENT_CHECKIN_NAMES = new String[] { diff --git a/core/java/android/os/LocaleList.java b/core/java/android/os/LocaleList.java index d7e440b66e13..c152c2d1abd4 100644 --- a/core/java/android/os/LocaleList.java +++ b/core/java/android/os/LocaleList.java @@ -37,6 +37,7 @@ import java.util.Locale; * LocaleList is an immutable list of Locales, typically used to keep an ordered list of user * preferences for locales. */ +@android.ravenwood.annotation.RavenwoodKeepWholeClass public final class LocaleList implements Parcelable { private final Locale[] mList; // This is a comma-separated list of the locales in the LocaleList created at construction time, diff --git a/core/java/android/os/Parcel.java b/core/java/android/os/Parcel.java index 136c45d1695f..47096dbbac61 100644 --- a/core/java/android/os/Parcel.java +++ b/core/java/android/os/Parcel.java @@ -434,7 +434,6 @@ public final class Parcel { @RavenwoodThrow private static native void nativeWriteStrongBinder(long nativePtr, IBinder val); @FastNative - @RavenwoodThrow private static native void nativeWriteFileDescriptor(long nativePtr, FileDescriptor val); private static native byte[] nativeCreateByteArray(long nativePtr); @@ -456,7 +455,6 @@ public final class Parcel { @RavenwoodThrow private static native IBinder nativeReadStrongBinder(long nativePtr); @FastNative - @RavenwoodThrow private static native FileDescriptor nativeReadFileDescriptor(long nativePtr); private static native long nativeCreate(); diff --git a/core/java/android/os/ParcelFileDescriptor.java b/core/java/android/os/ParcelFileDescriptor.java index 71957ee3461e..464df239b8fd 100644 --- a/core/java/android/os/ParcelFileDescriptor.java +++ b/core/java/android/os/ParcelFileDescriptor.java @@ -381,6 +381,8 @@ public class ParcelFileDescriptor implements Parcelable, Closeable { } private static void closeInternal$ravenwood(FileDescriptor fd) { + // Desktop JVM doesn't have FileDescriptor.close(), so we'll need to go to the ravenwood + // side to close it. native_close$ravenwood(fd); } diff --git a/core/java/android/os/PowerManagerInternal.java b/core/java/android/os/PowerManagerInternal.java index ce3156e4816f..1fb7937ff847 100644 --- a/core/java/android/os/PowerManagerInternal.java +++ b/core/java/android/os/PowerManagerInternal.java @@ -139,11 +139,16 @@ public abstract class PowerManagerInternal { * @param screenState The overridden screen state, or {@link Display#STATE_UNKNOWN} * to disable the override. * @param reason The reason for overriding the screen state. - * @param screenBrightness The overridden screen brightness, or - * {@link PowerManager#BRIGHTNESS_DEFAULT} to disable the override. + * @param screenBrightnessFloat The overridden screen brightness between + * {@link PowerManager#BRIGHTNESS_MIN} and {@link PowerManager#BRIGHTNESS_MAX}, or + * {@link PowerManager#BRIGHTNESS_INVALID_FLOAT} if screenBrightnessInt should be used instead. + * @param screenBrightnessInt The overridden screen brightness between 1 and 255, or + * {@link PowerManager#BRIGHTNESS_DEFAULT} to disable the override. Not used if + * screenBrightnessFloat is provided (is not NaN). */ public abstract void setDozeOverrideFromDreamManager( - int screenState, @Display.StateReason int reason, int screenBrightness); + int screenState, @Display.StateReason int reason, float screenBrightnessFloat, + int screenBrightnessInt); /** * Used by sidekick manager to tell the power manager if it shouldn't change the display state diff --git a/core/java/android/os/ServiceManager.java b/core/java/android/os/ServiceManager.java index e95c6a44c281..8aec7eb59e91 100644 --- a/core/java/android/os/ServiceManager.java +++ b/core/java/android/os/ServiceManager.java @@ -425,7 +425,7 @@ public final class ServiceManager { private static IBinder rawGetService(String name) throws RemoteException { final long start = sStatLogger.getTime(); - final IBinder binder = getIServiceManager().getService(name).getBinder(); + final IBinder binder = getIServiceManager().getService2(name).getBinder(); final int time = (int) sStatLogger.logDurationStat(Stats.GET_SERVICE, start); diff --git a/core/java/android/os/ServiceManagerNative.java b/core/java/android/os/ServiceManagerNative.java index 6c9a5c7f9fff..5a9c8787ee3b 100644 --- a/core/java/android/os/ServiceManagerNative.java +++ b/core/java/android/os/ServiceManagerNative.java @@ -57,8 +57,14 @@ class ServiceManagerProxy implements IServiceManager { return mRemote; } + // TODO(b/355394904): This function has been deprecated, please use getService2 instead. @UnsupportedAppUsage - public Service getService(String name) throws RemoteException { + public IBinder getService(String name) throws RemoteException { + // Same as checkService (old versions of servicemanager had both methods). + return checkService(name).getBinder(); + } + + public Service getService2(String name) throws RemoteException { // Same as checkService (old versions of servicemanager had both methods). return checkService(name); } diff --git a/core/java/android/os/UserManager.java b/core/java/android/os/UserManager.java index 3aa42c6bb594..392b6eb6d51b 100644 --- a/core/java/android/os/UserManager.java +++ b/core/java/android/os/UserManager.java @@ -6442,7 +6442,11 @@ public class UserManager { */ @UnsupportedAppUsage public int getUserSerialNumber(@UserIdInt int userId) { - if (android.multiuser.Flags.cacheUserSerialNumber()) { + // Read only flag should is to fix early access to this API + // cacheUserSerialNumber to be removed after the + // cacheUserSerialNumberReadOnly is fully rolled out + if (android.multiuser.Flags.cacheUserSerialNumberReadOnly() + || android.multiuser.Flags.cacheUserSerialNumber()) { // System user serial number is always 0, and it always exists. // There is no need to call binder for that. if (userId == UserHandle.USER_SYSTEM) { diff --git a/core/java/android/os/VibrationAttributes.java b/core/java/android/os/VibrationAttributes.java index 9df5b850188f..da863e58a882 100644 --- a/core/java/android/os/VibrationAttributes.java +++ b/core/java/android/os/VibrationAttributes.java @@ -16,6 +16,9 @@ package android.os; +import static android.os.vibrator.Flags.FLAG_VIBRATION_ATTRIBUTE_IME_USAGE_API; + +import android.annotation.FlaggedApi; import android.annotation.IntDef; import android.annotation.NonNull; import android.annotation.Nullable; @@ -55,6 +58,7 @@ public final class VibrationAttributes implements Parcelable { USAGE_PHYSICAL_EMULATION, USAGE_RINGTONE, USAGE_TOUCH, + USAGE_IME_FEEDBACK, }) @Retention(RetentionPolicy.SOURCE) public @interface Usage {} @@ -136,6 +140,12 @@ public final class VibrationAttributes implements Parcelable { */ public static final int USAGE_ACCESSIBILITY = 0x40 | USAGE_CLASS_FEEDBACK; /** + * Usage value to use for input method editor (IME) haptic feedback. + */ + @FlaggedApi(FLAG_VIBRATION_ATTRIBUTE_IME_USAGE_API) + public static final int USAGE_IME_FEEDBACK = 0x50 | USAGE_CLASS_FEEDBACK; + + /** * Usage value to use for media vibrations, such as music, movie, soundtrack, animations, games, * or any interactive media that isn't for touch feedback specifically. */ @@ -174,7 +184,6 @@ public final class VibrationAttributes implements Parcelable { FLAG_BYPASS_USER_VIBRATION_INTENSITY_OFF, FLAG_INVALIDATE_SETTINGS_CACHE, FLAG_PIPELINED_EFFECT, - FLAG_BYPASS_USER_VIBRATION_INTENSITY_SCALE }) @Retention(RetentionPolicy.SOURCE) public @interface Flag{} @@ -228,31 +237,12 @@ public final class VibrationAttributes implements Parcelable { public static final int FLAG_PIPELINED_EFFECT = 1 << 3; /** - * Flag requesting that this vibration effect to be played without applying the user - * intensity setting to scale the vibration. - * - * <p>The user setting is still applied to enable/disable the vibration, but the vibration - * effect strength will not be scaled based on the enabled setting value. - * - * <p>This is intended to be used on scenarios where the system needs to enforce a specific - * strength for the vibration effect, regardless of the user preference. Only privileged apps - * can ignore user settings, and this flag will be ignored otherwise. - * - * <p>If you need to bypass the user setting when it's disabling vibrations then this also - * needs the flag {@link #FLAG_BYPASS_USER_VIBRATION_INTENSITY_OFF} to be set. - * - * @hide - */ - public static final int FLAG_BYPASS_USER_VIBRATION_INTENSITY_SCALE = 1 << 4; - - /** * All flags supported by vibrator service, update it when adding new flag. * @hide */ public static final int FLAG_ALL_SUPPORTED = FLAG_BYPASS_INTERRUPTION_POLICY | FLAG_BYPASS_USER_VIBRATION_INTENSITY_OFF - | FLAG_INVALIDATE_SETTINGS_CACHE | FLAG_PIPELINED_EFFECT - | FLAG_BYPASS_USER_VIBRATION_INTENSITY_SCALE; + | FLAG_INVALIDATE_SETTINGS_CACHE | FLAG_PIPELINED_EFFECT; /** Creates a new {@link VibrationAttributes} instance with given usage. */ public static @NonNull VibrationAttributes createForUsage(@Usage int usage) { @@ -349,6 +339,7 @@ public final class VibrationAttributes implements Parcelable { case USAGE_RINGTONE: return AudioAttributes.USAGE_NOTIFICATION_RINGTONE; case USAGE_TOUCH: + case USAGE_IME_FEEDBACK: return AudioAttributes.USAGE_ASSISTANCE_SONIFICATION; case USAGE_ALARM: return AudioAttributes.USAGE_ALARM; @@ -447,6 +438,8 @@ public final class VibrationAttributes implements Parcelable { return "PHYSICAL_EMULATION"; case USAGE_HARDWARE_FEEDBACK: return "HARDWARE_FEEDBACK"; + case USAGE_IME_FEEDBACK: + return "IME"; default: return "unknown usage " + usage; } diff --git a/core/java/android/os/vibrator/VibrationConfig.java b/core/java/android/os/vibrator/VibrationConfig.java index f6e73b39f84b..a4164e9f204c 100644 --- a/core/java/android/os/vibrator/VibrationConfig.java +++ b/core/java/android/os/vibrator/VibrationConfig.java @@ -20,6 +20,7 @@ import static android.os.VibrationAttributes.USAGE_ACCESSIBILITY; import static android.os.VibrationAttributes.USAGE_ALARM; import static android.os.VibrationAttributes.USAGE_COMMUNICATION_REQUEST; import static android.os.VibrationAttributes.USAGE_HARDWARE_FEEDBACK; +import static android.os.VibrationAttributes.USAGE_IME_FEEDBACK; import static android.os.VibrationAttributes.USAGE_MEDIA; import static android.os.VibrationAttributes.USAGE_NOTIFICATION; import static android.os.VibrationAttributes.USAGE_PHYSICAL_EMULATION; @@ -67,6 +68,8 @@ public class VibrationConfig { private final int mDefaultNotificationVibrationIntensity; @VibrationIntensity private final int mDefaultRingVibrationIntensity; + @VibrationIntensity + private final int mDefaultKeyboardVibrationIntensity; private final boolean mKeyboardVibrationSettingsSupported; @@ -98,6 +101,8 @@ public class VibrationConfig { com.android.internal.R.integer.config_defaultNotificationVibrationIntensity); mDefaultRingVibrationIntensity = loadDefaultIntensity(resources, com.android.internal.R.integer.config_defaultRingVibrationIntensity); + mDefaultKeyboardVibrationIntensity = loadDefaultIntensity(resources, + com.android.internal.R.integer.config_defaultKeyboardVibrationIntensity); } @VibrationIntensity @@ -213,6 +218,9 @@ public class VibrationConfig { case USAGE_PHYSICAL_EMULATION: case USAGE_ACCESSIBILITY: return mDefaultHapticFeedbackIntensity; + case USAGE_IME_FEEDBACK: + return isKeyboardVibrationSettingsSupported() + ? mDefaultKeyboardVibrationIntensity : mDefaultHapticFeedbackIntensity; case USAGE_MEDIA: case USAGE_UNKNOWN: // fall through @@ -236,6 +244,7 @@ public class VibrationConfig { + ", mDefaultMediaIntensity=" + mDefaultMediaVibrationIntensity + ", mDefaultNotificationIntensity=" + mDefaultNotificationVibrationIntensity + ", mDefaultRingIntensity=" + mDefaultRingVibrationIntensity + + ", mDefaultKeyboardIntensity=" + mDefaultKeyboardVibrationIntensity + ", mKeyboardVibrationSettingsSupported=" + mKeyboardVibrationSettingsSupported + "}"; } diff --git a/core/java/android/os/vibrator/flags.aconfig b/core/java/android/os/vibrator/flags.aconfig index f4e2a7e28d8c..67c346401804 100644 --- a/core/java/android/os/vibrator/flags.aconfig +++ b/core/java/android/os/vibrator/flags.aconfig @@ -64,3 +64,24 @@ flag { purpose: PURPOSE_FEATURE } } + +flag { + namespace: "haptics" + name: "throttle_vibration_params_requests" + description: "Control the frequency of vibration params requests to prevent overloading the vendor service" + bug: "355320860" + metadata { + purpose: PURPOSE_BUGFIX + } +} + +flag { + namespace: "haptics" + name: "vibration_attribute_ime_usage_api" + is_exported: true + description: "A public API for IME usage vibration attribute" + bug: "332661766" + metadata { + purpose: PURPOSE_FEATURE + } +} diff --git a/core/java/android/provider/Settings.java b/core/java/android/provider/Settings.java index 850b9795e41a..0ee6f43e1329 100644 --- a/core/java/android/provider/Settings.java +++ b/core/java/android/provider/Settings.java @@ -12560,6 +12560,14 @@ public final class Settings { "contextual_screen_timeout_enabled"; /** + * Whether hinge angle lidevent is enabled. + * + * @hide + */ + public static final String HINGE_ANGLE_LIDEVENT_ENABLED = + "hinge_angle_lidevent_enabled"; + + /** * Whether lockscreen weather is enabled. * * @hide @@ -15812,7 +15820,7 @@ public final class Settings { * The following keys are supported: * * <pre> - * screen_brightness_array (int[]) + * screen_brightness_array (int[], values in range [1, 255]) * dimming_scrim_array (int[]) * prox_screen_off_delay (long) * prox_cooldown_trigger (long) diff --git a/core/java/android/service/dreams/DreamService.java b/core/java/android/service/dreams/DreamService.java index d4547167ce87..06e53ac8e7a2 100644 --- a/core/java/android/service/dreams/DreamService.java +++ b/core/java/android/service/dreams/DreamService.java @@ -74,6 +74,7 @@ import android.view.accessibility.AccessibilityEvent; import com.android.internal.R; import com.android.internal.annotations.VisibleForTesting; +import com.android.internal.display.BrightnessSynchronizer; import com.android.internal.util.DumpUtils; import java.io.FileDescriptor; @@ -269,6 +270,7 @@ public class DreamService extends Service implements Window.Callback { private volatile int mDozeScreenState = Display.STATE_UNKNOWN; private volatile @Display.StateReason int mDozeScreenStateReason = Display.STATE_REASON_UNKNOWN; private volatile int mDozeScreenBrightness = PowerManager.BRIGHTNESS_DEFAULT; + private volatile float mDozeScreenBrightnessFloat = PowerManager.BRIGHTNESS_INVALID_FLOAT; private boolean mDebug = false; @@ -927,12 +929,12 @@ public class DreamService extends Service implements Window.Callback { try { if (startAndStopDozingInBackground()) { mDreamManager.startDozingOneway( - mDreamToken, mDozeScreenState, mDozeScreenStateReason, - mDozeScreenBrightness); + mDreamToken, mDozeScreenState, mDozeScreenStateReason, + mDozeScreenBrightnessFloat, mDozeScreenBrightness); } else { mDreamManager.startDozing( mDreamToken, mDozeScreenState, mDozeScreenStateReason, - mDozeScreenBrightness); + mDozeScreenBrightnessFloat, mDozeScreenBrightness); } } catch (RemoteException ex) { @@ -1057,7 +1059,7 @@ public class DreamService extends Service implements Window.Callback { * Gets the screen brightness to use while dozing. * * @return The screen brightness while dozing as a value between - * {@link PowerManager#BRIGHTNESS_OFF} (0) and {@link PowerManager#BRIGHTNESS_ON} (255), + * {@link PowerManager#BRIGHTNESS_OFF + 1} (1) and {@link PowerManager#BRIGHTNESS_ON} (255), * or {@link PowerManager#BRIGHTNESS_DEFAULT} (-1) to ask the system to apply * its default policy based on the screen state. * @@ -1078,11 +1080,11 @@ public class DreamService extends Service implements Window.Callback { * The dream may set a different brightness before starting to doze and may adjust * the brightness while dozing to conserve power and achieve various effects. * </p><p> - * Note that dream may specify any brightness in the full 0-255 range, including + * Note that dream may specify any brightness in the full 1-255 range, including * values that are less than the minimum value for manual screen brightness - * adjustments by the user. In particular, the value may be set to 0 which may - * turn off the backlight entirely while still leaving the screen on although - * this behavior is device dependent and not guaranteed. + * adjustments by the user. In particular, the value may be set to + * {@link PowerManager.BRIGHTNESS_OFF} which may turn off the backlight entirely while still + * leaving the screen on although this behavior is device dependent and not guaranteed. * </p><p> * The available range of display brightness values and their behavior while dozing is * hardware dependent and may vary across devices. The dream may therefore @@ -1090,7 +1092,7 @@ public class DreamService extends Service implements Window.Callback { * </p> * * @param brightness The screen brightness while dozing as a value between - * {@link PowerManager#BRIGHTNESS_OFF} (0) and {@link PowerManager#BRIGHTNESS_ON} (255), + * {@link PowerManager#BRIGHTNESS_OFF + 1} (1) and {@link PowerManager#BRIGHTNESS_ON} (255), * or {@link PowerManager#BRIGHTNESS_DEFAULT} (-1) to ask the system to apply * its default policy based on the screen state. * @@ -1108,6 +1110,44 @@ public class DreamService extends Service implements Window.Callback { } /** + * Sets the screen brightness to use while dozing. + * <p> + * The value of this property determines the power state of the primary display + * once {@link #startDozing} has been called. The default value is + * {@link PowerManager#BRIGHTNESS_INVALID_FLOAT} which lets the system decide. + * The dream may set a different brightness before starting to doze and may adjust + * the brightness while dozing to conserve power and achieve various effects. + * </p><p> + * Note that dream may specify any brightness in the full 0-1 range, including + * values that are less than the minimum value for manual screen brightness + * adjustments by the user. In particular, the value may be set to + * {@link PowerManager#BRIGHTNESS_OFF_FLOAT} which may turn off the backlight entirely while + * still leaving the screen on although this behavior is device dependent and not guaranteed. + * </p><p> + * The available range of display brightness values and their behavior while dozing is + * hardware dependent and may vary across devices. The dream may therefore + * need to be modified or configured to correctly support the hardware. + * </p> + * + * @param brightness The screen brightness while dozing as a value between + * {@link PowerManager#BRIGHTNESS_MIN} (0) and {@link PowerManager#BRIGHTNESS_MAX} (1), + * or {@link PowerManager#BRIGHTNESS_INVALID_FLOAT} (Float.NaN) to ask the system to apply + * its default policy based on the screen state. + * + * @hide For use by system UI components only. + */ + @UnsupportedAppUsage + public void setDozeScreenBrightnessFloat(float brightness) { + if (!Float.isNaN(brightness)) { + brightness = clampAbsoluteBrightnessFloat(brightness); + } + if (!BrightnessSynchronizer.floatEquals(mDozeScreenBrightnessFloat, brightness)) { + mDozeScreenBrightnessFloat = brightness; + updateDoze(); + } + } + + /** * Called when this Dream is constructed. */ @Override @@ -1346,7 +1386,11 @@ public class DreamService extends Service implements Window.Callback { Slog.w(mTag, "WakeUp was called before the dream was attached."); } else { try { - mDreamManager.finishSelf(mDreamToken, false /*immediate*/); + if (startAndStopDozingInBackground()) { + mDreamManager.finishSelfOneway(mDreamToken, false /*immediate*/); + } else { + mDreamManager.finishSelf(mDreamToken, false /*immediate*/); + } } catch (RemoteException ex) { // system server died } @@ -1497,7 +1541,11 @@ public class DreamService extends Service implements Window.Callback { if (mFinished || mWaking) { Slog.w(mTag, "attach() called after dream already finished"); try { - mDreamManager.finishSelf(dreamToken, true /*immediate*/); + if (startAndStopDozingInBackground()) { + mDreamManager.finishSelfOneway(dreamToken, true /*immediate*/); + } else { + mDreamManager.finishSelf(dreamToken, true /*immediate*/); + } } catch (RemoteException ex) { // system server died } @@ -1743,6 +1791,13 @@ public class DreamService extends Service implements Window.Callback { return MathUtils.constrain(value, PowerManager.BRIGHTNESS_OFF, PowerManager.BRIGHTNESS_ON); } + private static float clampAbsoluteBrightnessFloat(float value) { + if (value == PowerManager.BRIGHTNESS_OFF_FLOAT) { + return value; + } + return MathUtils.constrain(value, PowerManager.BRIGHTNESS_MIN, PowerManager.BRIGHTNESS_MAX); + } + /** * The DreamServiceWrapper is used as a gateway to the system_server, where DreamController * uses it to control the DreamService. It is also used to receive callbacks from the diff --git a/core/java/android/service/dreams/IDreamManager.aidl b/core/java/android/service/dreams/IDreamManager.aidl index 76f63631e76a..611e7912517b 100644 --- a/core/java/android/service/dreams/IDreamManager.aidl +++ b/core/java/android/service/dreams/IDreamManager.aidl @@ -42,7 +42,8 @@ interface IDreamManager { /** @deprecated Please use finishSelfOneway instead. */ void finishSelf(in IBinder token, boolean immediate); /** @deprecated Please use startDozingOneway instead. */ - void startDozing(in IBinder token, int screenState, int reason, int screenBrightness); + void startDozing(in IBinder token, int screenState, int reason, float screenBrightnessFloat, + int screenBrightnessInt); void stopDozing(in IBinder token); void forceAmbientDisplayEnabled(boolean enabled); ComponentName[] getDreamComponentsForUser(int userId); @@ -52,6 +53,7 @@ interface IDreamManager { void startDreamActivity(in Intent intent); @JavaPassthrough(annotation="@android.annotation.RequiresPermission(android.Manifest.permission.WRITE_DREAM_STATE)") oneway void setDreamIsObscured(in boolean isObscured); - oneway void startDozingOneway(in IBinder token, int screenState, int reason, int screenBrightness); + oneway void startDozingOneway(in IBinder token, int screenState, int reason, + float screenBrightnessFloat, int screenBrightnessInt); oneway void finishSelfOneway(in IBinder token, boolean immediate); } diff --git a/core/java/android/text/DynamicLayout.java b/core/java/android/text/DynamicLayout.java index a78a417300ab..6b1aef710e50 100644 --- a/core/java/android/text/DynamicLayout.java +++ b/core/java/android/text/DynamicLayout.java @@ -1320,7 +1320,11 @@ public class DynamicLayout extends Layout { // It's possible that a Span is removed when the text covering it is // deleted, in this case, the original start and end of the span might be // OOB. So it'll reflow the entire string instead. - reflow(s, 0, 0, s.length()); + if (Flags.insertModeCrashUpdateLayoutSpan()) { + transformAndReflow(s, 0, s.length()); + } else { + reflow(s, 0, 0, s.length()); + } } else { reflow(s, start, end - start, end - start); } @@ -1343,7 +1347,11 @@ public class DynamicLayout extends Layout { // When text is changed, it'll also trigger onSpanChanged. In this case we // can't determine the updated range in the transformed text. So it'll // reflow the entire range instead. - reflow(s, 0, 0, s.length()); + if (Flags.insertModeCrashUpdateLayoutSpan()) { + transformAndReflow(s, 0, s.length()); + } else { + reflow(s, 0, 0, s.length()); + } } else { reflow(s, start, end - start, end - start); reflow(s, nstart, nend - nstart, nend - nstart); diff --git a/core/java/android/text/flags/flags.aconfig b/core/java/android/text/flags/flags.aconfig index 155a3e483d82..88a1b9c562d3 100644 --- a/core/java/android/text/flags/flags.aconfig +++ b/core/java/android/text/flags/flags.aconfig @@ -125,6 +125,16 @@ flag { } flag { + name: "insert_mode_crash_update_layout_span" + namespace: "text" + description: "Fix insert mode crash when the text has UpdateLayout span attached." + bug: "355137282" + metadata { + purpose: PURPOSE_BUGFIX + } +} + +flag { name: "icu_bidi_migration" namespace: "text" description: "A flag for replacing AndroidBidi with android.icu.text.Bidi." diff --git a/core/java/android/view/InputEventAssigner.java b/core/java/android/view/InputEventAssigner.java index 7fac6c5e4af6..30d9aaa4b144 100644 --- a/core/java/android/view/InputEventAssigner.java +++ b/core/java/android/view/InputEventAssigner.java @@ -17,7 +17,8 @@ package android.view; import static android.os.IInputConstants.INVALID_INPUT_EVENT_ID; -import static android.view.InputDevice.SOURCE_TOUCHSCREEN; +import static android.view.InputDevice.SOURCE_CLASS_POINTER; +import static android.view.InputDevice.SOURCE_CLASS_POSITION; /** * Process input events and assign input event id to a specific frame. @@ -64,18 +65,19 @@ public class InputEventAssigner { public int processEvent(InputEvent event) { if (event instanceof MotionEvent) { MotionEvent motionEvent = (MotionEvent) event; - if (motionEvent.isFromSource(SOURCE_TOUCHSCREEN)) { + if (motionEvent.isFromSource(SOURCE_CLASS_POINTER) || motionEvent.isFromSource( + SOURCE_CLASS_POSITION)) { final int action = motionEvent.getActionMasked(); if (action == MotionEvent.ACTION_DOWN) { mHasUnprocessedDown = true; mDownEventId = event.getId(); } - if (mHasUnprocessedDown && action == MotionEvent.ACTION_MOVE) { - return mDownEventId; - } if (action == MotionEvent.ACTION_CANCEL || action == MotionEvent.ACTION_UP) { mHasUnprocessedDown = false; } + if (mHasUnprocessedDown) { + return mDownEventId; + } } } return event.getId(); diff --git a/core/java/android/view/SurfaceControl.java b/core/java/android/view/SurfaceControl.java index 634469dd52ff..cf329d3b3992 100644 --- a/core/java/android/view/SurfaceControl.java +++ b/core/java/android/view/SurfaceControl.java @@ -164,6 +164,9 @@ public final class SurfaceControl implements Parcelable { float width, float height, float vecX, float vecY, float maxStretchAmountX, float maxStretchAmountY, float childRelativeLeft, float childRelativeTop, float childRelativeRight, float childRelativeBottom); + private static native void nativeSetEdgeExtensionEffect(long transactionObj, long nativeObj, + boolean leftEdge, boolean rightEdge, + boolean topEdge, boolean bottomEdge); private static native void nativeSetTrustedOverlay(long transactionObj, long nativeObject, int isTrustedOverlay); private static native void nativeSetDropInputMode( @@ -3513,6 +3516,19 @@ public final class SurfaceControl implements Parcelable { /** * @hide */ + public Transaction setEdgeExtensionEffect(SurfaceControl sc, int edge) { + checkPreconditions(sc); + + nativeSetEdgeExtensionEffect( + mNativeObject, sc.mNativeObject, + (edge & WindowInsets.Side.LEFT) != 0, (edge & WindowInsets.Side.RIGHT) != 0, + (edge & WindowInsets.Side.TOP) != 0, (edge & WindowInsets.Side.BOTTOM) != 0); + return this; + } + + /** + * @hide + */ @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.O) public Transaction setLayerStack(SurfaceControl sc, int layerStack) { checkPreconditions(sc); @@ -4882,4 +4898,5 @@ public final class SurfaceControl implements Parcelable { public static void notifyShutdown() { nativeNotifyShutdown(); } + } diff --git a/core/java/android/view/View.java b/core/java/android/view/View.java index 64c77661d9f4..5f8bea1cdc47 100644 --- a/core/java/android/view/View.java +++ b/core/java/android/view/View.java @@ -34071,14 +34071,21 @@ public class View implements Drawable.Callback, KeyEvent.Callback, } private float convertVelocityToFrameRate(float velocityPps) { - // From UXR study, premium experience is: - // 1500+ dp/s: 120fps - // 0 - 1500 dp/s: 80fps - // OEMs are likely to modify this to balance battery and user experience for their - // specific device. + // Internal testing has shown that this gives a premium experience: + // above 300dp/s => 120fps + // between 300dp/s and 125fps => 80fps + // below 125dp/s => 60fps float density = mAttachInfo.mDensity; float velocityDps = velocityPps / density; - return (velocityDps >= 1500f) ? MAX_FRAME_RATE : 80f; + float frameRate; + if (velocityDps > 300f) { + frameRate = MAX_FRAME_RATE; // Use maximum at fast motion + } else if (velocityDps > 125f) { + frameRate = 80f; // Use medium frame rate when motion is slower + } else { + frameRate = 60f; // Use minimum frame rate when motion is very slow + } + return frameRate; } /** diff --git a/core/java/android/view/ViewRootImpl.java b/core/java/android/view/ViewRootImpl.java index 9e52a1458bc8..9518abfe220b 100644 --- a/core/java/android/view/ViewRootImpl.java +++ b/core/java/android/view/ViewRootImpl.java @@ -145,7 +145,6 @@ import android.annotation.Size; import android.annotation.UiContext; import android.app.ActivityManager; import android.app.ActivityThread; -import android.app.ICompatCameraControlCallback; import android.app.ResourcesManager; import android.app.WindowConfiguration; import android.app.compat.CompatChanges; @@ -516,17 +515,6 @@ public final class ViewRootImpl implements ViewParent, int newDisplayId, @Nullable ActivityWindowInfo activityWindowInfo) { onConfigurationChanged(overrideConfig, newDisplayId); } - - /** - * Notify the corresponding activity about the request to show or hide a camera compat - * control for stretched issues in the viewfinder. - * - * @param showControl Whether the control should be shown or hidden. - * @param transformationApplied Whether the treatment is already applied. - * @param callback The callback executed when the user clicks on a control. - */ - void requestCompatCameraControl(boolean showControl, boolean transformationApplied, - ICompatCameraControlCallback callback); } /** @@ -12503,20 +12491,6 @@ public final class ViewRootImpl implements ViewParent, } } - /** - * Shows or hides a Camera app compat toggle for stretched issues with the requested state - * for the corresponding activity. - * - * @param showControl Whether the control should be shown or hidden. - * @param transformationApplied Whether the treatment is already applied. - * @param callback The callback executed when the user clicks on a control. - */ - public void requestCompatCameraControl(boolean showControl, boolean transformationApplied, - ICompatCameraControlCallback callback) { - mActivityConfigCallback.requestCompatCameraControl( - showControl, transformationApplied, callback); - } - boolean wasRelayoutRequested() { return mRelayoutRequested; } diff --git a/core/java/android/view/accessibility/AccessibilityCache.java b/core/java/android/view/accessibility/AccessibilityCache.java index f3cde43ff25b..376e66f81636 100644 --- a/core/java/android/view/accessibility/AccessibilityCache.java +++ b/core/java/android/view/accessibility/AccessibilityCache.java @@ -19,6 +19,7 @@ package android.view.accessibility; import static android.view.accessibility.AccessibilityNodeInfo.FOCUS_ACCESSIBILITY; +import android.annotation.Nullable; import android.os.Build; import android.os.SystemClock; import android.util.ArraySet; @@ -48,6 +49,8 @@ public class AccessibilityCache { private boolean mEnabled = true; + private final SparseArray<String> mWindowIdToEventSourceClassName = new SparseArray<>(); + /** * {@link AccessibilityEvent} types that are critical for the cache to stay up to date * @@ -273,8 +276,11 @@ public class AccessibilityCache { clearSubTreeLocked(event.getWindowId(), event.getSourceNodeId()); } break; - case AccessibilityEvent.TYPE_WINDOWS_CHANGED: + case AccessibilityEvent.TYPE_WINDOWS_CHANGED: { mValidWindowCacheTimeStamp = event.getEventTime(); + if (event.getWindowChanges() == AccessibilityEvent.WINDOWS_CHANGE_REMOVED) { + mWindowIdToEventSourceClassName.remove(event.getWindowId()); + } if (event.getWindowChanges() == AccessibilityEvent.WINDOWS_CHANGE_ACCESSIBILITY_FOCUSED) { // Don't need to clear all cache. Unless the changes are related to @@ -282,8 +288,15 @@ public class AccessibilityCache { clearWindowCacheLocked(); break; } + clear(); + } + break; case AccessibilityEvent.TYPE_WINDOW_STATE_CHANGED: { mValidWindowCacheTimeStamp = event.getEventTime(); + if (event.getContentChangeTypes() == 0 && event.getClassName() != null) { + mWindowIdToEventSourceClassName.put(event.getWindowId(), + event.getClassName().toString()); + } clear(); } break; } @@ -907,6 +920,12 @@ public class AccessibilityCache { } } + /** Returns the source class associated with the window with the given id. */ + @Nullable + public String getEventSourceClassName(int windowId) { + return mWindowIdToEventSourceClassName.get(windowId); + } + // Layer of indirection included to break dependency chain for testing public static class AccessibilityNodeRefresher { /** Refresh the given AccessibilityNodeInfo object. */ diff --git a/core/java/android/view/accessibility/AccessibilityNodeInfo.java b/core/java/android/view/accessibility/AccessibilityNodeInfo.java index 90cfcb1e64a8..a5ba294d6a19 100644 --- a/core/java/android/view/accessibility/AccessibilityNodeInfo.java +++ b/core/java/android/view/accessibility/AccessibilityNodeInfo.java @@ -982,7 +982,6 @@ public class AccessibilityNodeInfo implements Parcelable { private long mParentNodeId = UNDEFINED_NODE_ID; private long mLabelForId = UNDEFINED_NODE_ID; private long mLabeledById = UNDEFINED_NODE_ID; - private LongArray mLabeledByIds; private long mTraversalBefore = UNDEFINED_NODE_ID; private long mTraversalAfter = UNDEFINED_NODE_ID; @@ -3600,131 +3599,6 @@ public class AccessibilityNodeInfo implements Parcelable { } /** - * Adds the view which serves as the label of the view represented by - * this info for accessibility purposes. When more than one labels are - * added, the content from each label is combined in the order that - * they are added. - * <p> - * If visible text can be used to describe or give meaning to this UI, - * this method is preferred. For example, a TextView before an EditText - * in the UI usually specifies what information is contained in the - * EditText. Hence, the EditText is labelled by the TextView. - * </p> - * - * @param label A view that labels this node's source. - */ - @FlaggedApi(Flags.FLAG_SUPPORT_MULTIPLE_LABELEDBY) - public void addLabeledBy(@NonNull View label) { - addLabeledBy(label, AccessibilityNodeProvider.HOST_VIEW_ID); - } - - /** - * Adds the view which serves as the label of the view represented by - * this info for accessibility purposes. If <code>virtualDescendantId</code> - * is {@link View#NO_ID} the root is set as the label. When more than one - * labels are added, the content from each label is combined in the order - * that they are added. - * <p> - * A virtual descendant is an imaginary View that is reported as a part of the view - * hierarchy for accessibility purposes. This enables custom views that draw complex - * content to report themselves as a tree of virtual views, thus conveying their - * logical structure. - * </p> - * <p> - * If visible text can be used to describe or give meaning to this UI, - * this method is preferred. For example, a TextView before an EditText - * in the UI usually specifies what information is contained in the - * EditText. Hence, the EditText is labelled by the TextView. - * </p> - * <p> - * <strong>Note:</strong> Cannot be called from an - * {@link android.accessibilityservice.AccessibilityService}. - * This class is made immutable before being delivered to an AccessibilityService. - * </p> - * - * @param root A root whose virtual descendant labels this node's source. - * @param virtualDescendantId The id of the virtual descendant. - */ - @FlaggedApi(Flags.FLAG_SUPPORT_MULTIPLE_LABELEDBY) - public void addLabeledBy(@NonNull View root, int virtualDescendantId) { - enforceNotSealed(); - Preconditions.checkNotNull(root, "%s must not be null", root); - if (mLabeledByIds == null) { - mLabeledByIds = new LongArray(); - } - mLabeledById = makeNodeId(root.getAccessibilityViewId(), virtualDescendantId); - mLabeledByIds.add(mLabeledById); - } - - /** - * Gets the list of node infos which serve as the labels of the view represented by - * this info for accessibility purposes. - * - * @return The list of labels in the order that they were added. - */ - @FlaggedApi(Flags.FLAG_SUPPORT_MULTIPLE_LABELEDBY) - public @NonNull List<AccessibilityNodeInfo> getLabeledByList() { - enforceSealed(); - List<AccessibilityNodeInfo> labels = new ArrayList<>(); - if (mLabeledByIds == null) { - return labels; - } - for (int i = 0; i < mLabeledByIds.size(); i++) { - labels.add(getNodeForAccessibilityId(mConnectionId, mWindowId, mLabeledByIds.get(i))); - } - return labels; - } - - /** - * Removes a label. If the label was not previously added to the node, - * calling this method has no effect. - * <p> - * <strong>Note:</strong> Cannot be called from an - * {@link android.accessibilityservice.AccessibilityService}. - * This class is made immutable before being delivered to an AccessibilityService. - * </p> - * - * @param label The node which serves as this node's label. - * @return true if the label was present - * @see #addLabeledBy(View) - */ - @FlaggedApi(Flags.FLAG_SUPPORT_MULTIPLE_LABELEDBY) - public boolean removeLabeledBy(@NonNull View label) { - return removeLabeledBy(label, AccessibilityNodeProvider.HOST_VIEW_ID); - } - - /** - * Removes a virtual label which is a descendant of the given - * <code>root</code>. If the label was not previously added to the node, - * calling this method has no effect. - * - * @param root The root of the virtual subtree. - * @param virtualDescendantId The id of the virtual node which serves as this node's label. - * @return true if the label was present - * @see #addLabeledBy(View, int) - */ - @FlaggedApi(Flags.FLAG_SUPPORT_MULTIPLE_LABELEDBY) - public boolean removeLabeledBy(@NonNull View root, int virtualDescendantId) { - enforceNotSealed(); - final LongArray labeledByIds = mLabeledByIds; - if (labeledByIds == null) { - return false; - } - final int rootAccessibilityViewId = - (root != null) ? root.getAccessibilityViewId() : UNDEFINED_ITEM_ID; - final long labeledById = makeNodeId(rootAccessibilityViewId, virtualDescendantId); - if (mLabeledById == labeledById) { - mLabeledById = UNDEFINED_NODE_ID; - } - final int index = labeledByIds.indexOf(labeledById); - if (index < 0) { - return false; - } - labeledByIds.remove(index); - return true; - } - - /** * Sets the view which serves as the label of the view represented by * this info for accessibility purposes. * @@ -3757,17 +3631,7 @@ public class AccessibilityNodeInfo implements Parcelable { enforceNotSealed(); final int rootAccessibilityViewId = (root != null) ? root.getAccessibilityViewId() : UNDEFINED_ITEM_ID; - if (Flags.supportMultipleLabeledby()) { - if (mLabeledByIds == null) { - mLabeledByIds = new LongArray(); - } else { - mLabeledByIds.clear(); - } - } mLabeledById = makeNodeId(rootAccessibilityViewId, virtualDescendantId); - if (Flags.supportMultipleLabeledby()) { - mLabeledByIds.add(mLabeledById); - } } /** @@ -4378,12 +4242,6 @@ public class AccessibilityNodeInfo implements Parcelable { fieldIndex++; if (mLabeledById != DEFAULT.mLabeledById) nonDefaultFields |= bitAt(fieldIndex); fieldIndex++; - if (Flags.supportMultipleLabeledby()) { - if (!LongArray.elementsEqual(mLabeledByIds, DEFAULT.mLabeledByIds)) { - nonDefaultFields |= bitAt(fieldIndex); - } - fieldIndex++; - } if (mTraversalBefore != DEFAULT.mTraversalBefore) nonDefaultFields |= bitAt(fieldIndex); fieldIndex++; if (mTraversalAfter != DEFAULT.mTraversalAfter) nonDefaultFields |= bitAt(fieldIndex); @@ -4525,20 +4383,6 @@ public class AccessibilityNodeInfo implements Parcelable { if (isBitSet(nonDefaultFields, fieldIndex++)) parcel.writeLong(mParentNodeId); if (isBitSet(nonDefaultFields, fieldIndex++)) parcel.writeLong(mLabelForId); if (isBitSet(nonDefaultFields, fieldIndex++)) parcel.writeLong(mLabeledById); - if (Flags.supportMultipleLabeledby()) { - if (isBitSet(nonDefaultFields, fieldIndex++)) { - final LongArray labeledByIds = mLabeledByIds; - if (labeledByIds == null) { - parcel.writeInt(0); - } else { - final int labeledByIdsSize = labeledByIds.size(); - parcel.writeInt(labeledByIdsSize); - for (int i = 0; i < labeledByIdsSize; i++) { - parcel.writeLong(labeledByIds.get(i)); - } - } - } - } if (isBitSet(nonDefaultFields, fieldIndex++)) parcel.writeLong(mTraversalBefore); if (isBitSet(nonDefaultFields, fieldIndex++)) parcel.writeLong(mTraversalAfter); if (isBitSet(nonDefaultFields, fieldIndex++)) { @@ -4706,9 +4550,6 @@ public class AccessibilityNodeInfo implements Parcelable { mParentNodeId = other.mParentNodeId; mLabelForId = other.mLabelForId; mLabeledById = other.mLabeledById; - if (Flags.supportMultipleLabeledby()) { - mLabeledByIds = other.mLabeledByIds; - } mTraversalBefore = other.mTraversalBefore; mTraversalAfter = other.mTraversalAfter; mMinDurationBetweenContentChanges = other.mMinDurationBetweenContentChanges; @@ -4815,20 +4656,6 @@ public class AccessibilityNodeInfo implements Parcelable { if (isBitSet(nonDefaultFields, fieldIndex++)) mParentNodeId = parcel.readLong(); if (isBitSet(nonDefaultFields, fieldIndex++)) mLabelForId = parcel.readLong(); if (isBitSet(nonDefaultFields, fieldIndex++)) mLabeledById = parcel.readLong(); - if (Flags.supportMultipleLabeledby()) { - if (isBitSet(nonDefaultFields, fieldIndex++)) { - final int labeledByIdsSize = parcel.readInt(); - if (labeledByIdsSize <= 0) { - mLabeledByIds = null; - } else { - mLabeledByIds = new LongArray(labeledByIdsSize); - for (int i = 0; i < labeledByIdsSize; i++) { - final long labeledById = parcel.readLong(); - mLabeledByIds.add(labeledById); - } - } - } - } if (isBitSet(nonDefaultFields, fieldIndex++)) mTraversalBefore = parcel.readLong(); if (isBitSet(nonDefaultFields, fieldIndex++)) mTraversalAfter = parcel.readLong(); if (isBitSet(nonDefaultFields, fieldIndex++)) { diff --git a/core/java/android/view/animation/Animation.java b/core/java/android/view/animation/Animation.java index 09306c791537..2af935d5401f 100644 --- a/core/java/android/view/animation/Animation.java +++ b/core/java/android/view/animation/Animation.java @@ -28,6 +28,7 @@ import android.os.Handler; import android.os.SystemProperties; import android.util.AttributeSet; import android.util.TypedValue; +import android.view.WindowInsets; import dalvik.system.CloseGuard; @@ -881,12 +882,13 @@ public abstract class Animation implements Cloneable { } /** - * @return if a window animation has outsets applied to it. + * @return the edges to which outsets can be applied to * * @hide */ - public boolean hasExtension() { - return false; + @WindowInsets.Side.InsetsSide + public int getExtensionEdges() { + return 0x0; } /** diff --git a/core/java/android/view/animation/AnimationSet.java b/core/java/android/view/animation/AnimationSet.java index 5aaa994f3f8f..bbdc9d0392ba 100644 --- a/core/java/android/view/animation/AnimationSet.java +++ b/core/java/android/view/animation/AnimationSet.java @@ -21,6 +21,7 @@ import android.content.res.TypedArray; import android.graphics.RectF; import android.os.Build; import android.util.AttributeSet; +import android.view.WindowInsets; import java.util.ArrayList; import java.util.List; @@ -540,12 +541,12 @@ public class AnimationSet extends Animation { /** @hide */ @Override - public boolean hasExtension() { + @WindowInsets.Side.InsetsSide + public int getExtensionEdges() { + int edge = 0x0; for (Animation animation : mAnimations) { - if (animation.hasExtension()) { - return true; - } + edge |= animation.getExtensionEdges(); } - return false; + return edge; } } diff --git a/core/java/android/view/animation/ExtendAnimation.java b/core/java/android/view/animation/ExtendAnimation.java index 210eb8a1ca9d..ed047c744007 100644 --- a/core/java/android/view/animation/ExtendAnimation.java +++ b/core/java/android/view/animation/ExtendAnimation.java @@ -20,6 +20,7 @@ import android.content.Context; import android.content.res.TypedArray; import android.graphics.Insets; import android.util.AttributeSet; +import android.view.WindowInsets; /** * An animation that controls the outset of an object. @@ -50,6 +51,8 @@ public class ExtendAnimation extends Animation { private float mToRightValue; private float mToBottomValue; + private int mExtensionEdges = 0x0; + /** * Constructor used when an ExtendAnimation is loaded from a resource. * @@ -151,9 +154,22 @@ public class ExtendAnimation extends Animation { /** @hide */ @Override - public boolean hasExtension() { - return mFromInsets.left < 0 || mFromInsets.top < 0 || mFromInsets.right < 0 - || mFromInsets.bottom < 0; + @WindowInsets.Side.InsetsSide + public int getExtensionEdges() { + mExtensionEdges = 0x0; + if (mFromLeftValue > 0 || mToLeftValue > 0) { + mExtensionEdges |= WindowInsets.Side.LEFT; + } + if (mFromRightValue > 0 || mToRightValue > 0) { + mExtensionEdges |= WindowInsets.Side.RIGHT; + } + if (mFromTopValue > 0 || mToTopValue > 0) { + mExtensionEdges |= WindowInsets.Side.TOP; + } + if (mFromBottomValue > 0 || mToBottomValue > 0) { + mExtensionEdges |= WindowInsets.Side.BOTTOM; + } + return mExtensionEdges; } @Override diff --git a/core/java/android/view/autofill/AutofillClientController.java b/core/java/android/view/autofill/AutofillClientController.java index d505c733b3e9..95cae226ca85 100644 --- a/core/java/android/view/autofill/AutofillClientController.java +++ b/core/java/android/view/autofill/AutofillClientController.java @@ -582,4 +582,9 @@ public final class AutofillClientController implements AutofillManager.AutofillC Log.e(TAG, "authenticate() failed for intent:" + intent, e); } } + + @Override + public boolean isActivityResumed() { + return mActivity.isResumed(); + } } diff --git a/core/java/android/view/autofill/AutofillManager.java b/core/java/android/view/autofill/AutofillManager.java index 02a86c9eecb3..79ecfe1e9141 100644 --- a/core/java/android/view/autofill/AutofillManager.java +++ b/core/java/android/view/autofill/AutofillManager.java @@ -114,6 +114,7 @@ import java.util.ArrayList; import java.util.Arrays; import java.util.Collections; import java.util.List; +import java.util.Map; import java.util.Objects; import java.util.Set; import java.util.concurrent.atomic.AtomicBoolean; @@ -774,6 +775,13 @@ public final class AutofillManager { // dataset in responses. Used to avoid request pre-fill request again and again. private final ArraySet<AutofillId> mAllTrackedViews = new ArraySet<>(); + // Whether we need to re-attempt fill again. Needed for case of relayout. + private boolean mFillReAttemptNeeded = false; + + private Map<Integer, AutofillId> mFingerprintToViewMap = new ArrayMap<>(); + + private AutofillStateFingerprint mAutofillStateFingerprint; + /** @hide */ public interface AutofillClient { /** @@ -909,6 +917,11 @@ public final class AutofillManager { * @return An ID that is unique in the activity. */ @Nullable AutofillId autofillClientGetNextAutofillId(); + + /** + * @return Whether the activity is resumed or not. + */ + boolean isActivityResumed(); } /** @@ -919,6 +932,7 @@ public final class AutofillManager { mService = service; mOptions = context.getAutofillOptions(); mIsFillRequested = new AtomicBoolean(false); + mAutofillStateFingerprint = AutofillStateFingerprint.createInstance(); mIsFillDialogEnabled = AutofillFeatureFlags.isFillDialogEnabled(); mFillDialogEnabledHints = AutofillFeatureFlags.getFillDialogEnabledHints(); @@ -1357,6 +1371,20 @@ public final class AutofillManager { mOnInvisibleCalled = true; if (isExpiredResponse) { + if (mRelayoutFix && isAuthenticationPending()) { + Log.i(TAG, "onInvisibleForAutofill(): Ignoring expiringResponse due to pending" + + " authentication"); + try { + mService.notifyNotExpiringResponseDuringAuth( + mSessionId, mContext.getUserId()); + } catch (RemoteException e) { + // The failure could be a consequence of something going wrong on the + // server side. Do nothing here since it's just logging, but it's + // possible follow-up actions may fail. + } + return; + } + Log.i(TAG, "onInvisibleForAutofill(): expiringResponse"); // Notify service the response has expired. updateSessionLocked(/* id= */ null, /* bounds= */ null, /* value= */ null, ACTION_RESPONSE_EXPIRED, /* flags= */ 0); @@ -1513,14 +1541,29 @@ public final class AutofillManager { } /** + * Called to log notify view entered was ignored due to pending auth + * @hide + */ + public void notifyViewEnteredIgnoredDuringAuthCount() { + try { + mService.notifyViewEnteredIgnoredDuringAuthCount(mSessionId, mContext.getUserId()); + } catch (RemoteException e) { + // The failure could be a consequence of something going wrong on the + // server side. Do nothing here since it's just logging, but it's + // possible follow-up actions may fail. + } + } + + /** * Called to check if we should retry fill. * Useful for knowing whether to attempt refill after relayout. * * @hide */ public boolean shouldRetryFill() { - // TODO: Implement in follow-up cl - return false; + synchronized (mLock) { + return isAuthenticationPending() && mFillReAttemptNeeded; + } } /** @@ -1531,8 +1574,13 @@ public final class AutofillManager { */ public boolean attemptRefill() { Log.i(TAG, "Attempting refill"); - // TODO: Implement in follow-up cl - return false; + // Find active autofillable views. Compute their fingerprints + List<View> autofillableViews = + getClient().autofillClientFindAutofillableViewsByTraversal(); + if (sDebug) { + Log.d(TAG, "Autofillable views count:" + autofillableViews.size()); + } + return mAutofillStateFingerprint.attemptRefill(autofillableViews, this); } /** @@ -2493,7 +2541,13 @@ public final class AutofillManager { /** @hide */ public void onAuthenticationResult(int authenticationId, Intent data, View focusView) { + if (sVerbose) { + Log.v(TAG, "onAuthenticationResult(): authId= " + authenticationId + ", data=" + data); + } if (!hasAutofillFeature()) { + if (sVerbose) { + Log.v(TAG, "onAuthenticationResult(): autofill not enabled"); + } return; } // TODO: the result code is being ignored, so this method is not reliably @@ -2501,10 +2555,6 @@ public final class AutofillManager { // set the EXTRA_AUTHENTICATION_RESULT extra, but it could cause weird results if the // service set the extra and returned RESULT_CANCELED... - if (sDebug) { - Log.d(TAG, "onAuthenticationResult(): id= " + authenticationId + ", data=" + data); - } - synchronized (mLock) { if (!isActiveLocked()) { Log.w(TAG, "onAuthenticationResult(): sessionId=" + mSessionId + " not active"); @@ -2661,6 +2711,7 @@ public final class AutofillManager { mSessionId = receiver.getIntResult(); if (mSessionId != NO_SESSION) { mState = STATE_ACTIVE; + mAutofillStateFingerprint.setSessionId(mSessionId); } final int extraFlags = receiver.getOptionalExtraIntResult(0); if ((extraFlags & RECEIVER_FLAG_SESSION_FOR_AUGMENTED_AUTOFILL_ONLY) != 0) { @@ -2722,6 +2773,9 @@ public final class AutofillManager { if (resetEnteredIds) { mEnteredIds = null; } + mFillReAttemptNeeded = false; + mFingerprintToViewMap.clear(); + mAutofillStateFingerprint = AutofillStateFingerprint.createInstance(); } @GuardedBy("mLock") @@ -2984,8 +3038,12 @@ public final class AutofillManager { Intent fillInIntent, boolean authenticateInline) { synchronized (mLock) { if (sessionId == mSessionId) { - if (mRelayoutFixDeprecated) { + if (mRelayoutFixDeprecated || mRelayoutFix) { mState = STATE_PENDING_AUTHENTICATION; + if (sVerbose) { + Log.v(TAG, "entering STATE_PENDING_AUTHENTICATION : mRelayoutFix:" + + mRelayoutFix); + } } final AutofillClient client = getClient(); if (client != null) { @@ -3191,17 +3249,56 @@ public final class AutofillManager { @GuardedBy("mLock") private void handleFailedIdsLocked(@NonNull ArrayList<AutofillId> failedIds) { + handleFailedIdsLocked(failedIds, null, false, false); + } + + @GuardedBy("mLock") + private void handleFailedIdsLocked(@NonNull ArrayList<AutofillId> failedIds, + ArrayList<AutofillValue> failedAutofillValues, boolean hideHighlight, + boolean isRefill) { if (!failedIds.isEmpty() && sVerbose) { Log.v(TAG, "autofill(): total failed views: " + failedIds); } + + if (mRelayoutFix && !failedIds.isEmpty()) { + // Activity isn't in resumed state, so it's very possible that relayout could've + // occurred, so wait for it to declare proper failure. It's a temporary failure at the + // moment. We'll try again later when the activity is resumed. + + // The above doesn't seem to be the correct way. Look for pending auth cases. + // TODO(b/238252288): Check whether there was any auth done at all + mFillReAttemptNeeded = true; + mAutofillStateFingerprint.storeFailedIdsAndValues( + failedIds, failedAutofillValues, hideHighlight); + } try { - mService.setAutofillFailure(mSessionId, failedIds, mContext.getUserId()); + mService.setAutofillFailure(mSessionId, failedIds, isRefill, mContext.getUserId()); } catch (RemoteException e) { // In theory, we could ignore this error since it's not a big deal, but // in reality, we rather crash the app anyways, as the failure could be // a consequence of something going wrong on the server side... throw e.rethrowFromSystemServer(); } + if (mRelayoutFix && !failedIds.isEmpty()) { + if (!getClient().isActivityResumed()) { + if (sVerbose) { + Log.v(TAG, "handleFailedIdsLocked(): failed id's exist, but activity not" + + " resumed"); + } + } else { + if (isRefill) { + Log.i(TAG, "handleFailedIdsLocked(): Attempted refill, but failed"); + } else { + // activity has been resumed, try to re-fill + // getClient().isActivityResumed() && !failedIds.isEmpty() && !isRefill + // TODO(b/238252288): Do better state management, and only trigger the following + // if there was auth previously. + Log.i(TAG, "handleFailedIdsLocked(): Attempting refill"); + attemptRefill(); + mFillReAttemptNeeded = false; + } + } + } } private void autofill(int sessionId, List<AutofillId> ids, List<AutofillValue> values, @@ -3216,13 +3313,46 @@ public final class AutofillManager { return; } + final View[] views = client.autofillClientFindViewsByAutofillIdTraversal( + Helper.toArray(ids)); + + autofill(views, ids, values, hideHighlight, false); + } + } + + void autofill(View[] views, List<AutofillId> ids, List<AutofillValue> values, + boolean hideHighlight, boolean isRefill) { + if (sVerbose) { + Log.v(TAG, "autofill() ids:" + ids + " isRefill:" + isRefill); + } + synchronized (mLock) { + final AutofillClient client = getClient(); + if (client == null) { + return; + } + + if (ids == null) { + Log.i(TAG, "autofill(): No id's to fill"); + return; + } + + if (mRelayoutFix && isRefill) { + try { + mService.setAutofillIdsAttemptedForRefill( + mSessionId, ids, mContext.getUserId()); + } catch (RemoteException e) { + // The failure could be a consequence of something going wrong on the + // server side. Do nothing here since it's just logging, but it's + // possible follow-up actions may fail. + } + } + final int itemCount = ids.size(); int numApplied = 0; ArrayMap<View, SparseArray<AutofillValue>> virtualValues = null; - final View[] views = client.autofillClientFindViewsByAutofillIdTraversal( - Helper.toArray(ids)); ArrayList<AutofillId> failedIds = new ArrayList<>(); + ArrayList<AutofillValue> failedAutofillValues = new ArrayList<>(); if (mLastAutofilledData == null) { mLastAutofilledData = new ParcelableMap(itemCount); @@ -3237,7 +3367,9 @@ public final class AutofillManager { // the service; this is fine, but we need to update the view status in the // server side so it can be triggered again. Log.d(TAG, "autofill(): no View with id " + id); + // Possible relayout scenario failedIds.add(id); + failedAutofillValues.add(value); continue; } // Mark the view as to be autofilled with 'value' @@ -3268,7 +3400,8 @@ public final class AutofillManager { } } - handleFailedIdsLocked(failedIds); + handleFailedIdsLocked( + failedIds, failedAutofillValues, hideHighlight, isRefill); if (virtualValues != null) { for (int i = 0; i < virtualValues.size(); i++) { @@ -3322,7 +3455,7 @@ public final class AutofillManager { private void reportAutofillContentFailure(AutofillId id) { try { mService.setAutofillFailure(mSessionId, Collections.singletonList(id), - mContext.getUserId()); + false /* isRefill */, mContext.getUserId()); } catch (RemoteException e) { throw e.rethrowFromSystemServer(); } @@ -3349,20 +3482,22 @@ public final class AutofillManager { } /** - * Set the tracked views. + * Set the tracked views. * - * @param trackedIds The views to be tracked. + * @param trackedIds The views to be tracked. * @param saveOnAllViewsInvisible Finish the session once all tracked views are invisible. - * @param saveOnFinish Finish the session once the activity is finished. - * @param fillableIds Views that might anchor FillUI. - * @param saveTriggerId View that when clicked triggers commit(). + * @param saveOnFinish Finish the session once the activity is finished. + * @param fillableIds Views that might anchor FillUI. + * @param saveTriggerId View that when clicked triggers commit(). */ private void setTrackedViews(int sessionId, @Nullable AutofillId[] trackedIds, boolean saveOnAllViewsInvisible, boolean saveOnFinish, - @Nullable AutofillId[] fillableIds, @Nullable AutofillId saveTriggerId) { + @Nullable AutofillId[] fillableIds, @Nullable AutofillId saveTriggerId, + boolean shouldGrabViewFingerprints) { if (saveTriggerId != null) { saveTriggerId.resetSessionId(); } + final ArraySet<AutofillId> allFillableIds = new ArraySet<>(); synchronized (mLock) { if (sVerbose) { Log.v(TAG, "setTrackedViews(): sessionId=" + sessionId @@ -3372,6 +3507,7 @@ public final class AutofillManager { + ", fillableIds=" + Arrays.toString(fillableIds) + ", saveTrigerId=" + saveTriggerId + ", mFillableIds=" + mFillableIds + + ", shouldGrabViewFingerprints=" + shouldGrabViewFingerprints + ", mEnabled=" + mEnabled + ", mSessionId=" + mSessionId); } @@ -3405,7 +3541,6 @@ public final class AutofillManager { trackedIds = null; } - final ArraySet<AutofillId> allFillableIds = new ArraySet<>(); if (mFillableIds != null) { allFillableIds.addAll(mFillableIds); } @@ -3424,6 +3559,12 @@ public final class AutofillManager { mTrackedViews = null; } } + if (mRelayoutFix && shouldGrabViewFingerprints) { + // For all the views: tracked and others, calculate fingerprints and store them. + mAutofillStateFingerprint.setUseRelativePosition(mRelativePositionForRelayout); + mAutofillStateFingerprint.storeStatePriorToAuthentication( + getClient(), allFillableIds); + } } } @@ -3845,7 +3986,7 @@ public final class AutofillManager { @GuardedBy("mLock") private boolean isPendingAuthenticationLocked() { - return mRelayoutFixDeprecated && mState == STATE_PENDING_AUTHENTICATION; + return (mRelayoutFixDeprecated || mRelayoutFix) && mState == STATE_PENDING_AUTHENTICATION; } @GuardedBy("mLock") @@ -3858,7 +3999,7 @@ public final class AutofillManager { return mState == STATE_FINISHED; } - private void post(Runnable runnable) { + void post(Runnable runnable) { final AutofillClient client = getClient(); if (client == null) { if (sVerbose) Log.v(TAG, "ignoring post() because client is null"); @@ -4700,11 +4841,11 @@ public final class AutofillManager { @Override public void setTrackedViews(int sessionId, AutofillId[] ids, boolean saveOnAllViewsInvisible, boolean saveOnFinish, AutofillId[] fillableIds, - AutofillId saveTriggerId) { + AutofillId saveTriggerId, boolean shouldGrabViewFingerprints) { final AutofillManager afm = mAfm.get(); if (afm != null) { afm.post(() -> afm.setTrackedViews(sessionId, ids, saveOnAllViewsInvisible, - saveOnFinish, fillableIds, saveTriggerId)); + saveOnFinish, fillableIds, saveTriggerId, shouldGrabViewFingerprints)); } } diff --git a/core/java/android/view/autofill/AutofillStateFingerprint.java b/core/java/android/view/autofill/AutofillStateFingerprint.java new file mode 100644 index 000000000000..2db4285f0820 --- /dev/null +++ b/core/java/android/view/autofill/AutofillStateFingerprint.java @@ -0,0 +1,352 @@ +/* + * Copyright (C) 2024 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package android.view.autofill; + +import static android.view.autofill.Helper.sDebug; + +import android.annotation.NonNull; +import android.util.ArrayMap; +import android.util.Log; +import android.util.Slog; +import android.view.View; +import android.widget.TextView; + +import com.android.internal.annotations.VisibleForTesting; + +import java.util.ArrayList; +import java.util.Arrays; +import java.util.Collections; +import java.util.HashMap; +import java.util.List; +import java.util.Map; +import java.util.Objects; +import java.util.Set; + +/** + * This class manages and stores the autofillable views fingerprints for use in relayout situations. + * @hide + */ +@VisibleForTesting(visibility = VisibleForTesting.Visibility.PACKAGE) +public final class AutofillStateFingerprint { + + ArrayList<AutofillId> mPriorAutofillIds; + ArrayList<Integer> mViewHashCodes; // each entry corresponding to mPriorAutofillIds . + + boolean mHideHighlight = false; + + private int mSessionId; + + Map<Integer, AutofillId> mHashToAutofillIdMap = new ArrayMap<>(); + Map<AutofillId, AutofillId> mOldIdsToCurrentAutofillIdMap = new ArrayMap<>(); + + // These failed id's are attempted to be refilled again after relayout. + private ArrayList<AutofillId> mFailedIds = new ArrayList<>(); + private ArrayList<AutofillValue> mFailedAutofillValues = new ArrayList<>(); + + // whether to use relative positions for computing hashes. + private boolean mUseRelativePosition; + + private static final String TAG = "AutofillStateFingerprint"; + + /** + * Returns an instance of this class + */ + @VisibleForTesting(visibility = VisibleForTesting.Visibility.PACKAGE) + public static AutofillStateFingerprint createInstance() { + return new AutofillStateFingerprint(); + } + + private AutofillStateFingerprint() { + } + + /** + * Set sessionId for the instance + */ + void setSessionId(int sessionId) { + mSessionId = sessionId; + } + + /** + * Sets whether relative position of the views should be used to calculate fingerprints. + */ + void setUseRelativePosition(boolean useRelativePosition) { + mUseRelativePosition = useRelativePosition; + } + + /** + * Store the state of the views prior to the authentication. + */ + void storeStatePriorToAuthentication( + AutofillManager.AutofillClient client, Set<AutofillId> autofillIds) { + if (mUseRelativePosition) { + List<View> autofillableViews = client.autofillClientFindAutofillableViewsByTraversal(); + if (sDebug) { + Log.d(TAG, "Autofillable views count prior to auth:" + autofillableViews.size()); + } +// ArrayList<Integer> hashes = getFingerprintIds(autofillableViews); + + ArrayMap<Integer, View> hashes = getFingerprintIds(autofillableViews); + for (Map.Entry<Integer, View> entry : hashes.entrySet()) { + View view = entry.getValue(); + if (view != null) { + mHashToAutofillIdMap.put(entry.getKey(), view.getAutofillId()); + } else { + if (sDebug) { + Log.d(TAG, "Encountered null view"); + } + } + } + } else { + // Just use the provided autofillIds and get their hashes + if (sDebug) { + Log.d(TAG, "Size of autofillId's being stored: " + autofillIds.size() + + " list:" + autofillIds); + } + AutofillId[] autofillIdsArr = Helper.toArray(autofillIds); + View[] views = client.autofillClientFindViewsByAutofillIdTraversal(autofillIdsArr); + for (int i = 0; i < autofillIdsArr.length; i++) { + View view = views[i]; + if (view != null) { + int id = getEphemeralFingerprintId(view, 0 /* position irrelevant */); + AutofillId autofillId = view.getAutofillId(); + autofillId.setSessionId(mSessionId); + mHashToAutofillIdMap.put(id, autofillId); + } else { + if (sDebug) { + Log.d(TAG, "Encountered null view"); + } + } + } + } + } + + /** + * Store failed ids, so that they can be refilled later + */ + void storeFailedIdsAndValues( + @NonNull ArrayList<AutofillId> failedIds, + ArrayList<AutofillValue> failedAutofillValues, + boolean hideHighlight) { + for (AutofillId failedId : failedIds) { + if (failedId != null) { + failedId.setSessionId(mSessionId); + } else { + if (sDebug) { + Log.d(TAG, "Got null failed ids"); + } + } + } + mFailedIds = failedIds; + mFailedAutofillValues = failedAutofillValues; + mHideHighlight = hideHighlight; + } + + private void dumpCurrentState() { + Log.d(TAG, "FailedId's: " + mFailedIds); + Log.d(TAG, "Hashes from map" + mHashToAutofillIdMap); + } + + boolean attemptRefill( + List<View> currentAutofillableViews, @NonNull AutofillManager autofillManager) { + if (sDebug) { + dumpCurrentState(); + } + // For the autofillable views, compute their hashes + ArrayMap<Integer, View> currentHashes = getFingerprintIds(currentAutofillableViews); + + // For the computed hashes, try to look for the old fingerprints. + // If match found, update the new autofill ids of those views + Map<AutofillId, View> oldFailedIdsToCurrentViewMap = new HashMap<>(); + for (Map.Entry<Integer, View> entry : currentHashes.entrySet()) { + View view = entry.getValue(); + int currentHash = entry.getKey(); + AutofillId currentAutofillId = view.getAutofillId(); + currentAutofillId.setSessionId(mSessionId); + if (mHashToAutofillIdMap.containsKey(currentHash)) { + AutofillId oldAutofillId = mHashToAutofillIdMap.get(currentHash); + oldAutofillId.setSessionId(mSessionId); + mOldIdsToCurrentAutofillIdMap.put(oldAutofillId, currentAutofillId); + Log.i(TAG, "Mapping current autofill id: " + view.getAutofillId() + + " to existing autofill id " + oldAutofillId); + + oldFailedIdsToCurrentViewMap.put(oldAutofillId, view); + } else { + Log.i(TAG, "Couldn't map current autofill id: " + view.getAutofillId() + + " with currentHash:" + currentHash + " for view:" + view); + } + } + + int viewsCount = 0; + View[] views = new View[mFailedIds.size()]; + for (int i = 0; i < mFailedIds.size(); i++) { + AutofillId oldAutofillId = mFailedIds.get(i); + AutofillId currentAutofillId = mOldIdsToCurrentAutofillIdMap.get(oldAutofillId); + if (currentAutofillId == null) { + if (sDebug) { + Log.d(TAG, "currentAutofillId = null"); + } + } + mFailedIds.set(i, currentAutofillId); + views[i] = oldFailedIdsToCurrentViewMap.get(oldAutofillId); + if (views[i] != null) { + viewsCount++; + } + } + + if (sDebug) { + dumpCurrentState(); + } + + // Attempt autofill now + Slog.i(TAG, "Attempting refill of views. Found " + viewsCount + + " views to refill from previously " + mFailedIds.size() + + " failed ids:" + mFailedIds); + autofillManager.post( + () -> autofillManager.autofill( + views, mFailedIds, mFailedAutofillValues, mHideHighlight, + true /* isRefill */)); + + return false; + } + + /** + * Retrieves fingerprint hashes for the views + */ + ArrayMap<Integer, View> getFingerprintIds(@NonNull List<View> views) { + ArrayMap<Integer, View> map = new ArrayMap<>(); + if (mUseRelativePosition) { + Collections.sort(views, (View v1, View v2) -> { + int[] posV1 = v1.getLocationOnScreen(); + int[] posV2 = v2.getLocationOnScreen(); + + int compare = posV1[0] - posV2[0]; // x coordinate + if (compare != 0) { + return compare; + } + compare = posV1[1] - posV2[1]; // y coordinate + if (compare != 0) { + return compare; + } + // Sort on vertical + compare = compareTop(v1, v2); + if (compare != 0) { + return compare; + } + compare = compareBottom(v1, v2); + if (compare != 0) { + return compare; + } + compare = compareLeft(v1, v2); + if (compare != 0) { + return compare; + } + return compareRight(v1, v2); + // Note that if compareRight also returned 0, that means both the views have exact + // same location, so just treat them as equal + }); + } + for (int i = 0; i < views.size(); i++) { + View view = views.get(i); + map.put(getEphemeralFingerprintId(view, i), view); + } + return map; + } + + /** + * Returns fingerprint hash for the view. + */ + @VisibleForTesting(visibility = VisibleForTesting.Visibility.PRIVATE) + public int getEphemeralFingerprintId(View v, int position) { + if (v == null) return -1; + int inputType = Integer.MIN_VALUE; + int imeOptions = Integer.MIN_VALUE; + boolean isSingleLine = false; + CharSequence hints = ""; + if (v instanceof TextView) { + TextView tv = (TextView) v; + inputType = tv.getInputType(); + hints = tv.getHint(); + isSingleLine = tv.isSingleLine(); + imeOptions = tv.getImeOptions(); + // TODO(b/238252288): Consider adding more IME related fields. + } + CharSequence contentDesc = v.getContentDescription(); + CharSequence tooltip = v.getTooltipText(); + + int autofillType = v.getAutofillType(); + String[] autofillHints = v.getAutofillHints(); + int visibility = v.getVisibility(); + + int paddingLeft = v.getPaddingLeft(); + int paddingRight = v.getPaddingRight(); + int paddingTop = v.getPaddingTop(); + int paddingBottom = v.getPaddingBottom(); + + // TODO(b/238252288): Following are making relayout flaky. Do more analysis to figure out + // why. + int height = v.getHeight(); + int width = v.getWidth(); + + // Order doesn't matter much here. We can change the order, as long as we use the same + // order for storing and fetching fingerprints. The order can be changed in platform + // versions. + int hash = Objects.hash(visibility, inputType, imeOptions, isSingleLine, hints, + contentDesc, tooltip, autofillType, Arrays.deepHashCode(autofillHints), + paddingBottom, paddingTop, paddingRight, paddingLeft); + if (mUseRelativePosition) { + hash = Objects.hash(hash, position); + } + if (sDebug) { + Log.d(TAG, "Hash: " + hash + " for AutofillId:" + v.getAutofillId() + + " visibility:" + visibility + + " inputType:" + inputType + + " imeOptions:" + imeOptions + + " isSingleLine:" + isSingleLine + + " hints:" + hints + + " contentDesc:" + contentDesc + + " tooltipText:" + tooltip + + " autofillType:" + autofillType + + " autofillHints:" + Arrays.toString(autofillHints) + + " height:" + height + + " width:" + width + + " paddingLeft:" + paddingLeft + + " paddingRight:" + paddingRight + + " paddingTop:" + paddingTop + + " paddingBottom:" + paddingBottom + + " mUseRelativePosition" + mUseRelativePosition + + " position:" + position + ); + } + return hash; + } + + private int compareTop(View v1, View v2) { + return v1.getTop() - v2.getTop(); + } + + private int compareBottom(View v1, View v2) { + return v1.getBottom() - v2.getBottom(); + } + + private int compareLeft(View v1, View v2) { + return v1.getLeft() - v2.getLeft(); + } + + private int compareRight(View v1, View v2) { + return v1.getRight() - v2.getRight(); + } +} diff --git a/core/java/android/view/autofill/IAutoFillManager.aidl b/core/java/android/view/autofill/IAutoFillManager.aidl index 2039b4d5c1bd..f67405f7c1e4 100644 --- a/core/java/android/view/autofill/IAutoFillManager.aidl +++ b/core/java/android/view/autofill/IAutoFillManager.aidl @@ -48,7 +48,7 @@ oneway interface IAutoFillManager { in IResultReceiver result); void updateSession(int sessionId, in AutofillId id, in Rect bounds, in AutofillValue value, int action, int flags, int userId); - void setAutofillFailure(int sessionId, in List<AutofillId> ids, int userId); + void setAutofillFailure(int sessionId, in List<AutofillId> ids, boolean isRefill, int userId); void setViewAutofilled(int sessionId, in AutofillId id, int userId); void finishSession(int sessionId, int userId, int commitReason); void cancelSession(int sessionId, int userId); @@ -67,4 +67,7 @@ oneway interface IAutoFillManager { void getDefaultFieldClassificationAlgorithm(in IResultReceiver result); void setAugmentedAutofillWhitelist(in List<String> packages, in List<ComponentName> activities, in IResultReceiver result); + void notifyNotExpiringResponseDuringAuth(int sessionId, int userId); + void notifyViewEnteredIgnoredDuringAuthCount(int sessionId, int userId); + void setAutofillIdsAttemptedForRefill(int sessionId, in List<AutofillId> ids, int userId); } diff --git a/core/java/android/view/autofill/IAutoFillManagerClient.aidl b/core/java/android/view/autofill/IAutoFillManagerClient.aidl index 904a7e0d6173..39d71da1318c 100644 --- a/core/java/android/view/autofill/IAutoFillManagerClient.aidl +++ b/core/java/android/view/autofill/IAutoFillManagerClient.aidl @@ -72,7 +72,8 @@ oneway interface IAutoFillManagerClient { */ void setTrackedViews(int sessionId, in @nullable AutofillId[] savableIds, boolean saveOnAllViewsInvisible, boolean saveOnFinish, - in @nullable AutofillId[] fillableIds, in AutofillId saveTriggerId); + in @nullable AutofillId[] fillableIds, in AutofillId saveTriggerId, + in boolean shouldGrabViewFingerprints); /** * Requests showing the fill UI. diff --git a/core/java/android/view/inputmethod/IInputMethodManagerGlobalInvoker.java b/core/java/android/view/inputmethod/IInputMethodManagerGlobalInvoker.java index 07a97948e7fd..2f515fe7738c 100644 --- a/core/java/android/view/inputmethod/IInputMethodManagerGlobalInvoker.java +++ b/core/java/android/view/inputmethod/IInputMethodManagerGlobalInvoker.java @@ -196,16 +196,22 @@ final class IInputMethodManagerGlobalInvoker { /** * Invokes {@link IInputMethodManager#removeImeSurface()} + * + * @param displayId display ID from which this request originates + * @param exceptionHandler an optional {@link RemoteException} handler */ @AnyThread - @RequiresPermission(Manifest.permission.INTERNAL_SYSTEM_WINDOW) - static void removeImeSurface(@Nullable Consumer<RemoteException> exceptionHandler) { + @RequiresPermission(allOf = { + Manifest.permission.INTERNAL_SYSTEM_WINDOW, + Manifest.permission.INTERACT_ACROSS_USERS_FULL}) + static void removeImeSurface(int displayId, + @Nullable Consumer<RemoteException> exceptionHandler) { final IInputMethodManager service = getService(); if (service == null) { return; } try { - service.removeImeSurface(); + service.removeImeSurface(displayId); } catch (RemoteException e) { handleRemoteExceptionOrRethrow(e, exceptionHandler); } @@ -437,7 +443,9 @@ final class IInputMethodManagerGlobalInvoker { } @AnyThread - @RequiresPermission(Manifest.permission.WRITE_SECURE_SETTINGS) + @RequiresPermission(allOf = { + Manifest.permission.WRITE_SECURE_SETTINGS, + Manifest.permission.INTERACT_ACROSS_USERS_FULL}) static void showInputMethodPickerFromSystem(int auxiliarySubtypeMode, int displayId) { final IInputMethodManager service = getService(); if (service == null) { @@ -465,7 +473,9 @@ final class IInputMethodManagerGlobalInvoker { } @AnyThread - @RequiresPermission(Manifest.permission.WRITE_SECURE_SETTINGS) + @RequiresPermission(allOf = { + Manifest.permission.WRITE_SECURE_SETTINGS, + Manifest.permission.INTERACT_ACROSS_USERS_FULL}) static void onImeSwitchButtonClickFromSystem(int displayId) { final IInputMethodManager service = getService(); if (service == null) { diff --git a/core/java/android/view/inputmethod/InputMethodManagerGlobal.java b/core/java/android/view/inputmethod/InputMethodManagerGlobal.java index 5df9fd15c47a..244b2395d49f 100644 --- a/core/java/android/view/inputmethod/InputMethodManagerGlobal.java +++ b/core/java/android/view/inputmethod/InputMethodManagerGlobal.java @@ -95,11 +95,13 @@ public class InputMethodManagerGlobal { /** * Invokes {@link IInputMethodManager#removeImeSurface()} * + * @param displayId display ID from which this request originates. * @param exceptionHandler an optional {@link RemoteException} handler. */ @AnyThread @RequiresPermission(Manifest.permission.INTERNAL_SYSTEM_WINDOW) - public static void removeImeSurface(@Nullable Consumer<RemoteException> exceptionHandler) { - IInputMethodManagerGlobalInvoker.removeImeSurface(exceptionHandler); + public static void removeImeSurface(int displayId, + @Nullable Consumer<RemoteException> exceptionHandler) { + IInputMethodManagerGlobalInvoker.removeImeSurface(displayId, exceptionHandler); } } diff --git a/core/java/android/window/ITaskOrganizerController.aidl b/core/java/android/window/ITaskOrganizerController.aidl index 478aeece0888..1748b9d38538 100644 --- a/core/java/android/window/ITaskOrganizerController.aidl +++ b/core/java/android/window/ITaskOrganizerController.aidl @@ -67,7 +67,4 @@ interface ITaskOrganizerController { * Restarts the top activity in the given task by killing its process if it is visible. */ void restartTaskTopActivityProcessIfVisible(in WindowContainerToken task); - - /** Updates a state of camera compat control for stretched issues in the viewfinder. */ - void updateCameraCompatControlState(in WindowContainerToken task, int state); } diff --git a/core/java/android/window/TaskFragmentInfo.java b/core/java/android/window/TaskFragmentInfo.java index fa5195727afe..23a1224fcc4e 100644 --- a/core/java/android/window/TaskFragmentInfo.java +++ b/core/java/android/window/TaskFragmentInfo.java @@ -102,6 +102,8 @@ public final class TaskFragmentInfo implements Parcelable { @NonNull private final Point mMinimumDimensions = new Point(); + private final boolean mIsTopNonFishingChild; + /** @hide */ public TaskFragmentInfo( @NonNull IBinder fragmentToken, @NonNull WindowContainerToken token, @@ -110,7 +112,7 @@ public final class TaskFragmentInfo implements Parcelable { @NonNull List<IBinder> inRequestedTaskFragmentActivities, @NonNull Point positionInParent, boolean isTaskClearedForReuse, boolean isTaskFragmentClearedForPip, boolean isClearedForReorderActivityToFront, - @NonNull Point minimumDimensions) { + @NonNull Point minimumDimensions, boolean isTopNonFinishingChild) { mFragmentToken = requireNonNull(fragmentToken); mToken = requireNonNull(token); mConfiguration.setTo(configuration); @@ -123,6 +125,7 @@ public final class TaskFragmentInfo implements Parcelable { mIsTaskFragmentClearedForPip = isTaskFragmentClearedForPip; mIsClearedForReorderActivityToFront = isClearedForReorderActivityToFront; mMinimumDimensions.set(minimumDimensions); + mIsTopNonFishingChild = isTopNonFinishingChild; } @NonNull @@ -212,6 +215,16 @@ public final class TaskFragmentInfo implements Parcelable { } /** + * Indicates that this TaskFragment is the top non-finishing child of its parent container + * among all Activities and TaskFragment siblings. + * + * @hide + */ + public boolean isTopNonFinishingChild() { + return mIsTopNonFishingChild; + } + + /** * Returns {@code true} if the parameters that are important for task fragment organizers are * equal between this {@link TaskFragmentInfo} and {@param that}. * Note that this method is usually called with @@ -236,7 +249,8 @@ public final class TaskFragmentInfo implements Parcelable { && mIsTaskClearedForReuse == that.mIsTaskClearedForReuse && mIsTaskFragmentClearedForPip == that.mIsTaskFragmentClearedForPip && mIsClearedForReorderActivityToFront == that.mIsClearedForReorderActivityToFront - && mMinimumDimensions.equals(that.mMinimumDimensions); + && mMinimumDimensions.equals(that.mMinimumDimensions) + && mIsTopNonFishingChild == that.mIsTopNonFishingChild; } private TaskFragmentInfo(Parcel in) { @@ -252,6 +266,7 @@ public final class TaskFragmentInfo implements Parcelable { mIsTaskFragmentClearedForPip = in.readBoolean(); mIsClearedForReorderActivityToFront = in.readBoolean(); mMinimumDimensions.readFromParcel(in); + mIsTopNonFishingChild = in.readBoolean(); } /** @hide */ @@ -269,6 +284,7 @@ public final class TaskFragmentInfo implements Parcelable { dest.writeBoolean(mIsTaskFragmentClearedForPip); dest.writeBoolean(mIsClearedForReorderActivityToFront); mMinimumDimensions.writeToParcel(dest, flags); + dest.writeBoolean(mIsTopNonFishingChild); } @NonNull @@ -299,6 +315,7 @@ public final class TaskFragmentInfo implements Parcelable { + " isTaskFragmentClearedForPip=" + mIsTaskFragmentClearedForPip + " mIsClearedForReorderActivityToFront=" + mIsClearedForReorderActivityToFront + " minimumDimensions=" + mMinimumDimensions + + " isTopNonFinishingChild=" + mIsTopNonFishingChild + "}"; } diff --git a/core/java/android/window/TaskOrganizer.java b/core/java/android/window/TaskOrganizer.java index b9ffdbc0c2e4..3ecb619a7445 100644 --- a/core/java/android/window/TaskOrganizer.java +++ b/core/java/android/window/TaskOrganizer.java @@ -24,7 +24,6 @@ import android.annotation.RequiresPermission; import android.annotation.SuppressLint; import android.annotation.TestApi; import android.app.ActivityManager; -import android.app.CameraCompatTaskInfo.CameraCompatControlState; import android.os.IBinder; import android.os.RemoteException; import android.view.SurfaceControl; @@ -252,20 +251,6 @@ public class TaskOrganizer extends WindowOrganizer { } /** - * Updates a state of camera compat control for stretched issues in the viewfinder. - * @hide - */ - @RequiresPermission(android.Manifest.permission.MANAGE_ACTIVITY_TASKS) - public void updateCameraCompatControlState(@NonNull WindowContainerToken task, - @CameraCompatControlState int state) { - try { - mTaskOrganizerController.updateCameraCompatControlState(task, state); - } catch (RemoteException e) { - throw e.rethrowFromSystemServer(); - } - } - - /** * Gets the executor to run callbacks on. * @hide */ diff --git a/core/java/android/window/TransitionFilter.java b/core/java/android/window/TransitionFilter.java index ec4e3e9163fa..3cfde870de18 100644 --- a/core/java/android/window/TransitionFilter.java +++ b/core/java/android/window/TransitionFilter.java @@ -30,6 +30,8 @@ import android.os.Parcel; import android.os.Parcelable; import android.view.WindowManager; +import com.android.window.flags.Flags; + /** * A parcelable filter that can be used for rerouting transitions to a remote. This is a local * representation so that the transition system doesn't need to make blocking queries over @@ -183,6 +185,9 @@ public final class TransitionFilter implements Parcelable { public ComponentName mTopActivity; public IBinder mLaunchCookie; + /** If non-null, requires the change to specifically have or not-have a custom animation. */ + public Boolean mCustomAnimation = null; + public Requirement() { } @@ -196,6 +201,9 @@ public final class TransitionFilter implements Parcelable { mOrder = in.readInt(); mTopActivity = in.readTypedObject(ComponentName.CREATOR); mLaunchCookie = in.readStrongBinder(); + // 0: null, 1: false, 2: true + final int customAnimRaw = in.readInt(); + mCustomAnimation = customAnimRaw == 0 ? null : Boolean.valueOf(customAnimRaw == 2); } /** Go through changes and find if at-least one change matches this filter */ @@ -237,6 +245,23 @@ public final class TransitionFilter implements Parcelable { if (!matchesCookie(change.getTaskInfo())) { continue; } + if (mCustomAnimation != null + // only applies to activity/task + && (change.getTaskInfo() != null + || change.getActivityComponent() != null)) { + final TransitionInfo.AnimationOptions opts = + Flags.moveAnimationOptionsToChange() ? change.getAnimationOptions() + : info.getAnimationOptions(); + if (opts != null) { + boolean canActuallyOverride = change.getTaskInfo() == null + || opts.getOverrideTaskTransition(); + if (mCustomAnimation != canActuallyOverride) { + continue; + } + } else if (mCustomAnimation) { + continue; + } + } return true; } return false; @@ -286,6 +311,8 @@ public final class TransitionFilter implements Parcelable { dest.writeInt(mOrder); dest.writeTypedObject(mTopActivity, flags); dest.writeStrongBinder(mLaunchCookie); + int customAnimRaw = mCustomAnimation == null ? 0 : (mCustomAnimation ? 2 : 1); + dest.writeInt(customAnimRaw); } @NonNull @@ -327,6 +354,9 @@ public final class TransitionFilter implements Parcelable { out.append(" order=" + containerOrderToString(mOrder)); out.append(" topActivity=").append(mTopActivity); out.append(" launchCookie=").append(mLaunchCookie); + if (mCustomAnimation != null) { + out.append(" customAnim=").append(mCustomAnimation.booleanValue()); + } out.append("}"); return out.toString(); } diff --git a/core/java/android/window/flags/windowing_frontend.aconfig b/core/java/android/window/flags/windowing_frontend.aconfig index 76989f9ea2f4..e5a9b6ac55c8 100644 --- a/core/java/android/window/flags/windowing_frontend.aconfig +++ b/core/java/android/window/flags/windowing_frontend.aconfig @@ -65,14 +65,6 @@ flag { } flag { - name: "defer_display_updates" - namespace: "windowing_frontend" - description: "Feature flag for deferring DisplayManager updates to WindowManager if Shell transition is running" - bug: "259220649" - is_fixed_read_only: true -} - -flag { name: "close_to_square_config_includes_status_bar" namespace: "windowing_frontend" description: "On close to square display, when necessary, configuration includes status bar" @@ -158,17 +150,6 @@ flag { } flag { - name: "keyguard_appear_transition" - namespace: "windowing_frontend" - description: "Add transition when keyguard appears" - bug: "327970608" - is_fixed_read_only: true - metadata { - purpose: PURPOSE_BUGFIX - } -} - -flag { name: "get_dimmer_on_closing" namespace: "windowing_frontend" description: "Change check for when to ignore a closing task's dim" diff --git a/core/java/android/window/flags/windowing_sdk.aconfig b/core/java/android/window/flags/windowing_sdk.aconfig index 4230641e2e12..4c18bbfbeebf 100644 --- a/core/java/android/window/flags/windowing_sdk.aconfig +++ b/core/java/android/window/flags/windowing_sdk.aconfig @@ -51,13 +51,6 @@ flag { flag { namespace: "windowing_sdk" - name: "embedded_activity_back_nav_flag" - description: "Refines embedded activity back navigation behavior" - bug: "293642394" -} - -flag { - namespace: "windowing_sdk" name: "cover_display_opt_in" is_exported: true description: "Properties to allow apps and activities to opt-in to cover display rendering" diff --git a/core/java/com/android/internal/accessibility/AccessibilityShortcutController.java b/core/java/com/android/internal/accessibility/AccessibilityShortcutController.java index f9c294758bf0..e8831ec2743e 100644 --- a/core/java/com/android/internal/accessibility/AccessibilityShortcutController.java +++ b/core/java/com/android/internal/accessibility/AccessibilityShortcutController.java @@ -36,6 +36,7 @@ import android.content.ComponentName; import android.content.ContentResolver; import android.content.Context; import android.content.DialogInterface; +import android.content.Intent; import android.content.pm.PackageManager; import android.content.res.Configuration; import android.database.ContentObserver; @@ -63,6 +64,7 @@ import android.widget.Toast; import com.android.internal.R; import com.android.internal.accessibility.dialog.AccessibilityTarget; import com.android.internal.accessibility.util.ShortcutUtils; +import com.android.internal.annotations.VisibleForTesting; import com.android.internal.util.function.pooled.PooledLambda; import java.lang.annotation.Retention; @@ -122,6 +124,13 @@ public class AccessibilityShortcutController { .setContentType(AudioAttributes.CONTENT_TYPE_SONIFICATION) .setUsage(AudioAttributes.USAGE_ASSISTANCE_ACCESSIBILITY) .build(); + + /** + * An intent action to launch Extra Dim dialog. + */ + @VisibleForTesting + static final String ACTION_LAUNCH_REMOVE_EXTRA_DIM_DIALOG = + "com.android.systemui.action.LAUNCH_REMOVE_EXTRA_DIM_DIALOG"; private static Map<ComponentName, FrameworkFeatureInfo> sFrameworkShortcutFeaturesMap; private final Context mContext; @@ -846,7 +855,7 @@ public class AccessibilityShortcutController { if (com.android.server.display.feature.flags.Flags.evenDimmer() && context.getResources().getBoolean( com.android.internal.R.bool.config_evenDimmerEnabled)) { - launchExtraDimDialog(); + launchExtraDimDialog(context); return true; } else { // Assuming that the default state will be to have the feature off @@ -863,8 +872,12 @@ public class AccessibilityShortcutController { } } - private void launchExtraDimDialog() { - // TODO: launch Extra dim dialog for feature migration + private void launchExtraDimDialog(Context context) { + final Intent intent = new Intent(ACTION_LAUNCH_REMOVE_EXTRA_DIM_DIALOG); + intent.setFlags(Intent.FLAG_RECEIVER_FOREGROUND); + intent.setPackage( + context.getString(com.android.internal.R.string.config_systemUi)); + context.sendBroadcastAsUser(intent, UserHandle.SYSTEM); } } diff --git a/core/java/com/android/internal/accessibility/common/ShortcutConstants.java b/core/java/com/android/internal/accessibility/common/ShortcutConstants.java index a3fcfad7afc8..44dceb9b7edb 100644 --- a/core/java/com/android/internal/accessibility/common/ShortcutConstants.java +++ b/core/java/com/android/internal/accessibility/common/ShortcutConstants.java @@ -72,7 +72,8 @@ public final class ShortcutConstants { UserShortcutType.TRIPLETAP, UserShortcutType.TWOFINGER_DOUBLETAP, UserShortcutType.QUICK_SETTINGS, - UserShortcutType.GESTURE + UserShortcutType.GESTURE, + UserShortcutType.ALL }) public @interface UserShortcutType { int DEFAULT = 0; @@ -84,6 +85,7 @@ public final class ShortcutConstants { int QUICK_SETTINGS = 1 << 4; int GESTURE = 1 << 5; // LINT.ThenChange(:shortcut_type_array) + int ALL = SOFTWARE | HARDWARE | TRIPLETAP | TWOFINGER_DOUBLETAP | QUICK_SETTINGS | GESTURE; } /** diff --git a/core/java/com/android/internal/app/ChooserActivity.java b/core/java/com/android/internal/app/ChooserActivity.java index ab456a84d9ad..6258f5ca721a 100644 --- a/core/java/com/android/internal/app/ChooserActivity.java +++ b/core/java/com/android/internal/app/ChooserActivity.java @@ -544,6 +544,14 @@ public class ChooserActivity extends ResolverActivity implements @Override protected void onCreate(Bundle savedInstanceState) { + if (Settings.Secure.getIntForUser(getContentResolver(), + Settings.Secure.SECURE_FRP_MODE, 0, + getUserId()) == 1) { + Log.e(TAG, "Sharing disabled due to active FRP lock."); + super.onCreate(savedInstanceState); + finish(); + return; + } final long intentReceivedTime = System.currentTimeMillis(); mLatencyTracker.onActionStart(ACTION_LOAD_SHARE_SHEET); diff --git a/core/java/com/android/internal/view/IInputMethodManager.aidl b/core/java/com/android/internal/view/IInputMethodManager.aidl index cba27ce3fe65..b51678e82ed0 100644 --- a/core/java/com/android/internal/view/IInputMethodManager.aidl +++ b/core/java/com/android/internal/view/IInputMethodManager.aidl @@ -125,9 +125,9 @@ interface IInputMethodManager { void showInputMethodPickerFromClient(in IInputMethodClient client, int auxiliarySubtypeMode); - @EnforcePermission("WRITE_SECURE_SETTINGS") - @JavaPassthrough(annotation="@android.annotation.RequiresPermission(value = " - + "android.Manifest.permission.WRITE_SECURE_SETTINGS)") + @EnforcePermission(allOf = {"WRITE_SECURE_SETTINGS", "INTERACT_ACROSS_USERS_FULL"}) + @JavaPassthrough(annotation="@android.annotation.RequiresPermission(allOf = {android.Manifest." + + "permission.WRITE_SECURE_SETTINGS, android.Manifest.permission.INTERACT_ACROSS_USERS_FULL})") void showInputMethodPickerFromSystem(int auxiliarySubtypeMode, int displayId); @EnforcePermission("TEST_INPUT_METHOD") @@ -143,9 +143,9 @@ interface IInputMethodManager { * @param displayId The ID of the display where the input method picker dialog should be shown. * @param userId The ID of the user that triggered the click. */ - @EnforcePermission("WRITE_SECURE_SETTINGS") - @JavaPassthrough(annotation="@android.annotation.RequiresPermission(value = " - + "android.Manifest.permission.WRITE_SECURE_SETTINGS)") + @EnforcePermission(allOf = {"WRITE_SECURE_SETTINGS" ,"INTERACT_ACROSS_USERS_FULL"}) + @JavaPassthrough(annotation="@android.annotation.RequiresPermission(allOf = {android.Manifest." + + "permission.WRITE_SECURE_SETTINGS, android.Manifest.permission.INTERACT_ACROSS_USERS_FULL})") oneway void onImeSwitchButtonClickFromSystem(int displayId); @JavaPassthrough(annotation="@android.annotation.RequiresPermission(value = " @@ -168,10 +168,10 @@ interface IInputMethodManager { oneway void reportPerceptibleAsync(in IBinder windowToken, boolean perceptible); - @EnforcePermission("INTERNAL_SYSTEM_WINDOW") - @JavaPassthrough(annotation="@android.annotation.RequiresPermission(value = " - + "android.Manifest.permission.INTERNAL_SYSTEM_WINDOW)") - void removeImeSurface(); + @EnforcePermission(allOf = {"INTERNAL_SYSTEM_WINDOW", "INTERACT_ACROSS_USERS_FULL"}) + @JavaPassthrough(annotation="@android.annotation.RequiresPermission(allOf = {android.Manifest." + + "permission.INTERNAL_SYSTEM_WINDOW, android.Manifest.permission.INTERACT_ACROSS_USERS_FULL})") + void removeImeSurface(int displayId); /** Remove the IME surface. Requires passing the currently focused window. */ oneway void removeImeSurfaceFromWindowAsync(in IBinder windowToken); diff --git a/core/java/com/android/internal/widget/remotecompose/core/Operations.java b/core/java/com/android/internal/widget/remotecompose/core/Operations.java index fc8668e4c657..4b8dbf6365f9 100644 --- a/core/java/com/android/internal/widget/remotecompose/core/Operations.java +++ b/core/java/com/android/internal/widget/remotecompose/core/Operations.java @@ -37,6 +37,7 @@ import com.android.internal.widget.remotecompose.core.operations.DrawTweenPath; import com.android.internal.widget.remotecompose.core.operations.FloatConstant; import com.android.internal.widget.remotecompose.core.operations.FloatExpression; import com.android.internal.widget.remotecompose.core.operations.Header; +import com.android.internal.widget.remotecompose.core.operations.IntegerExpression; import com.android.internal.widget.remotecompose.core.operations.MatrixRestore; import com.android.internal.widget.remotecompose.core.operations.MatrixRotate; import com.android.internal.widget.remotecompose.core.operations.MatrixSave; @@ -54,6 +55,8 @@ import com.android.internal.widget.remotecompose.core.operations.TextFromFloat; import com.android.internal.widget.remotecompose.core.operations.TextMerge; import com.android.internal.widget.remotecompose.core.operations.Theme; import com.android.internal.widget.remotecompose.core.operations.utilities.IntMap; +import com.android.internal.widget.remotecompose.core.types.BooleanConstant; +import com.android.internal.widget.remotecompose.core.types.IntegerConstant; /** * List of operations supported in a RemoteCompose document @@ -109,6 +112,9 @@ public class Operations { public static final int TEXT_MERGE = 136; public static final int NAMED_VARIABLE = 137; public static final int COLOR_CONSTANT = 138; + public static final int DATA_INT = 140; + public static final int DATA_BOOLEAN = 143; + public static final int INTEGER_EXPRESSION = 144; /////////////////////////////////////////====================== public static IntMap<CompanionOperation> map = new IntMap<>(); @@ -153,6 +159,9 @@ public class Operations { map.put(TEXT_MERGE, TextMerge.COMPANION); map.put(NAMED_VARIABLE, NamedVariable.COMPANION); map.put(COLOR_CONSTANT, ColorConstant.COMPANION); + map.put(DATA_INT, IntegerConstant.COMPANION); + map.put(INTEGER_EXPRESSION, IntegerExpression.COMPANION); + map.put(DATA_BOOLEAN, BooleanConstant.COMPANION); } } diff --git a/core/java/com/android/internal/widget/remotecompose/core/PaintContext.java b/core/java/com/android/internal/widget/remotecompose/core/PaintContext.java index ecd0efceacf3..6d8a44297538 100644 --- a/core/java/com/android/internal/widget/remotecompose/core/PaintContext.java +++ b/core/java/com/android/internal/widget/remotecompose/core/PaintContext.java @@ -59,6 +59,16 @@ public abstract class PaintContext { public abstract void drawRect(float left, float top, float right, float bottom); + /** + * this caches the paint to a paint stack + */ + public abstract void savePaint(); + + /** + * This restores the paint form the paint stack + */ + public abstract void restorePaint(); + public abstract void drawRoundRect(float left, float top, float right, @@ -119,6 +129,10 @@ public abstract class PaintContext { float start, float stop); + /** + * This applies changes to the current paint + * @param mPaintData the list of changes + */ public abstract void applyPaint(PaintBundle mPaintData); /** diff --git a/core/java/com/android/internal/widget/remotecompose/core/RemoteComposeBuffer.java b/core/java/com/android/internal/widget/remotecompose/core/RemoteComposeBuffer.java index d462c7d64a5a..f5f155e3ab0b 100644 --- a/core/java/com/android/internal/widget/remotecompose/core/RemoteComposeBuffer.java +++ b/core/java/com/android/internal/widget/remotecompose/core/RemoteComposeBuffer.java @@ -37,6 +37,7 @@ import com.android.internal.widget.remotecompose.core.operations.DrawTweenPath; import com.android.internal.widget.remotecompose.core.operations.FloatConstant; import com.android.internal.widget.remotecompose.core.operations.FloatExpression; import com.android.internal.widget.remotecompose.core.operations.Header; +import com.android.internal.widget.remotecompose.core.operations.IntegerExpression; import com.android.internal.widget.remotecompose.core.operations.MatrixRestore; import com.android.internal.widget.remotecompose.core.operations.MatrixRotate; import com.android.internal.widget.remotecompose.core.operations.MatrixSave; @@ -55,6 +56,7 @@ import com.android.internal.widget.remotecompose.core.operations.Theme; import com.android.internal.widget.remotecompose.core.operations.Utils; import com.android.internal.widget.remotecompose.core.operations.paint.PaintBundle; import com.android.internal.widget.remotecompose.core.operations.utilities.easing.FloatAnimation; +import com.android.internal.widget.remotecompose.core.types.IntegerConstant; import java.io.File; import java.io.FileInputStream; @@ -876,6 +878,27 @@ public class RemoteComposeBuffer { return Utils.asNan(id); } + + /** + * Add a Integer return an id number pointing to that float. + * @param value + * @return + */ + public int addInteger(int value) { + int id = mRemoteComposeState.cacheInteger(value); + IntegerConstant.COMPANION.apply(mBuffer, id, value); + return id; + } + + /** + * Add a IntegerId as float ID. + * @param id id to be converted + * @return + */ + public float asFloatId(int id) { + return Utils.asNan(id); + } + /** * Add a float that is a computation based on variables * @param value A RPN style float operation i.e. "4, 3, ADD" outputs 7 @@ -901,6 +924,18 @@ public class RemoteComposeBuffer { } /** + * Add and integer expression + * @param mask defines which elements are operators or variables + * @param value array of values to calculate maximum 32 + * @return + */ + public int addIntegerExpression(int mask, int[] value) { + int id = mRemoteComposeState.cache(value); + IntegerExpression.COMPANION.apply(mBuffer, id, mask, value); + return id; + } + + /** * Add a simple color * @param color * @return id that represents that color @@ -1038,5 +1073,6 @@ public class RemoteComposeBuffer { NamedVariable.COMPANION.apply(mBuffer, id, NamedVariable.COLOR_TYPE, name); } + } diff --git a/core/java/com/android/internal/widget/remotecompose/core/RemoteComposeState.java b/core/java/com/android/internal/widget/remotecompose/core/RemoteComposeState.java index bfe67c8e9d19..6b06a544be40 100644 --- a/core/java/com/android/internal/widget/remotecompose/core/RemoteComposeState.java +++ b/core/java/com/android/internal/widget/remotecompose/core/RemoteComposeState.java @@ -21,6 +21,8 @@ import static com.android.internal.widget.remotecompose.core.RemoteContext.ID_TI import static com.android.internal.widget.remotecompose.core.RemoteContext.ID_WINDOW_HEIGHT; import static com.android.internal.widget.remotecompose.core.RemoteContext.ID_WINDOW_WIDTH; +import com.android.internal.widget.remotecompose.core.operations.utilities.IntFloatMap; +import com.android.internal.widget.remotecompose.core.operations.utilities.IntIntMap; import com.android.internal.widget.remotecompose.core.operations.utilities.IntMap; import java.util.ArrayList; @@ -37,16 +39,12 @@ public class RemoteComposeState { private final IntMap<Object> mIntDataMap = new IntMap<>(); private final IntMap<Boolean> mIntWrittenMap = new IntMap<>(); private final HashMap<Object, Integer> mDataIntMap = new HashMap(); - private final float[] mFloatMap = new float[MAX_FLOATS]; // efficient cache - private final int[] mColorMap = new int[MAX_COLORS]; // efficient cache + private final IntFloatMap mFloatMap = new IntFloatMap(); // efficient cache + private final IntIntMap mIntegerMap = new IntIntMap(); // efficient cache + private final IntIntMap mColorMap = new IntIntMap(); // efficient cache private final boolean[] mColorOverride = new boolean[MAX_COLORS]; private int mNextId = START_ID; - { - for (int i = 0; i < mFloatMap.length; i++) { - mFloatMap[i] = Float.NaN; - } - } /** * Get Object based on id. The system will cache things like bitmaps @@ -113,29 +111,62 @@ public class RemoteComposeState { */ public int cacheFloat(float item) { int id = nextId(); - mFloatMap[id] = item; + mFloatMap.put(id, item); + mIntegerMap.put(id, (int) item); return id; } /** * Insert an item in the cache */ - public void cacheFloat(int id, float item) { - mFloatMap[id] = item; + public int cacheInteger(int item) { + int id = nextId(); + mIntegerMap.put(id, item); + mFloatMap.put(id, item); + return id; } /** * Insert an item in the cache */ + public void cacheFloat(int id, float item) { + mFloatMap.put(id, item); + } + + /** + * Insert an float item in the cache + */ public void updateFloat(int id, float item) { - mFloatMap[id] = item; + mFloatMap.put(id, item); + mIntegerMap.put(id, (int) item); } /** - * get float + * Insert an integer item in the cache + */ + public void updateInteger(int id, int item) { + mFloatMap.put(id, item); + mIntegerMap.put(id, item); + } + + /** + * get a float from the float cache + * + * @param id of the float value + * @return the float value */ public float getFloat(int id) { - return mFloatMap[id]; + return mFloatMap.get(id); + } + + /** + * get an integer from the cache + * + * @param id of the integer value + * @return the integer + */ + public int getInteger(int id) { + return mIntegerMap.get(id); } /** @@ -145,11 +176,12 @@ public class RemoteComposeState { * @return */ public int getColor(int id) { - return mColorMap[id]; + return mColorMap.get(id); } /** * Modify the color at id. + * * @param id * @param color */ @@ -157,7 +189,7 @@ public class RemoteComposeState { if (mColorOverride[id]) { return; } - mColorMap[id] = color; + mColorMap.put(id, color); } /** @@ -169,7 +201,7 @@ public class RemoteComposeState { */ public void overrideColor(int id, int color) { mColorOverride[id] = true; - mColorMap[id] = color; + mColorMap.put(id, color); } /** @@ -205,6 +237,7 @@ public class RemoteComposeState { /** * Get the next available id + * * @return */ public int nextId() { @@ -213,6 +246,7 @@ public class RemoteComposeState { /** * Set the next id + * * @param id */ public void setNextId(int id) { @@ -234,6 +268,7 @@ public class RemoteComposeState { /** * Commands that listen to variables add themselves. + * * @param id * @param variableSupport */ @@ -243,6 +278,7 @@ public class RemoteComposeState { /** * List of Commands that need to be updated + * * @param context * @return */ @@ -264,6 +300,7 @@ public class RemoteComposeState { /** * Set the width of the overall document on screen. + * * @param width */ public void setWindowWidth(float width) { @@ -272,6 +309,7 @@ public class RemoteComposeState { /** * Set the width of the overall document on screen. + * * @param height */ public void setWindowHeight(float height) { diff --git a/core/java/com/android/internal/widget/remotecompose/core/RemoteContext.java b/core/java/com/android/internal/widget/remotecompose/core/RemoteContext.java index 32027d8b535c..41eeb5bdd476 100644 --- a/core/java/com/android/internal/widget/remotecompose/core/RemoteContext.java +++ b/core/java/com/android/internal/widget/remotecompose/core/RemoteContext.java @@ -39,6 +39,7 @@ public abstract class RemoteContext { public float mWidth = 0f; public float mHeight = 0f; + private float mAnimationTime; /** * Load a path under an id. @@ -65,11 +66,20 @@ public abstract class RemoteContext { public abstract void loadColor(int id, int color); /** + * Set the animation time allowing the creator to control animation rates + * @param time + */ + public void setAnimationTime(float time) { + mAnimationTime = time; + } + + /** * gets the time animation clock as float in seconds * @return a monotonic time in seconds (arbitrary zero point) */ public float getAnimationTime() { - return (System.nanoTime() - mStart) * 1E-9f; + mAnimationTime = (System.nanoTime() - mStart) * 1E-9f; // Eliminate + return mAnimationTime; } /** @@ -213,6 +223,13 @@ public abstract class RemoteContext { public abstract void loadFloat(int id, float value); /** + * Load a float + * @param id + * @param value + */ + public abstract void loadInteger(int id, int value); + + /** * Load an animated float associated with an id * Todo: Remove? * @param id @@ -235,6 +252,13 @@ public abstract class RemoteContext { public abstract float getFloat(int id); /** + * Get a float given an id + * @param id + * @return + */ + public abstract int getInteger(int id); + + /** * Get the color given and ID * @param id * @return diff --git a/core/java/com/android/internal/widget/remotecompose/core/operations/DrawBase3.java b/core/java/com/android/internal/widget/remotecompose/core/operations/DrawBase3.java index 56b2f1f7bb86..5a4a9f3754df 100644 --- a/core/java/com/android/internal/widget/remotecompose/core/operations/DrawBase3.java +++ b/core/java/com/android/internal/widget/remotecompose/core/operations/DrawBase3.java @@ -63,23 +63,23 @@ public abstract class DrawBase3 extends PaintOperation @Override public void updateVariables(RemoteContext context) { - mV1 = (Float.isNaN(mValue1)) + mV1 = (Utils.isVariable(mValue1)) ? context.getFloat(Utils.idFromNan(mValue1)) : mValue1; - mV2 = (Float.isNaN(mValue2)) + mV2 = (Utils.isVariable(mValue2)) ? context.getFloat(Utils.idFromNan(mValue2)) : mValue2; - mV3 = (Float.isNaN(mValue3)) + mV3 = (Utils.isVariable(mValue3)) ? context.getFloat(Utils.idFromNan(mValue3)) : mValue3; } @Override public void registerListening(RemoteContext context) { - if (Float.isNaN(mValue1)) { + if (Utils.isVariable(mValue1)) { context.listensTo(Utils.idFromNan(mValue1), this); } - if (Float.isNaN(mValue2)) { + if (Utils.isVariable(mValue2)) { context.listensTo(Utils.idFromNan(mValue2), this); } - if (Float.isNaN(mValue3)) { + if (Utils.isVariable(mValue3)) { context.listensTo(Utils.idFromNan(mValue3), this); } } diff --git a/core/java/com/android/internal/widget/remotecompose/core/operations/DrawTextRun.java b/core/java/com/android/internal/widget/remotecompose/core/operations/DrawTextRun.java deleted file mode 100644 index a0992528d981..000000000000 --- a/core/java/com/android/internal/widget/remotecompose/core/operations/DrawTextRun.java +++ /dev/null @@ -1,121 +0,0 @@ -/* - * Copyright (C) 2024 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package com.android.internal.widget.remotecompose.core.operations; - -import com.android.internal.widget.remotecompose.core.CompanionOperation; -import com.android.internal.widget.remotecompose.core.Operation; -import com.android.internal.widget.remotecompose.core.Operations; -import com.android.internal.widget.remotecompose.core.PaintContext; -import com.android.internal.widget.remotecompose.core.PaintOperation; -import com.android.internal.widget.remotecompose.core.WireBuffer; - -import java.util.List; - -public class DrawTextRun extends PaintOperation { - public static final Companion COMPANION = new Companion(); - int mTextID; - int mStart = 0; - int mEnd = 0; - int mContextStart = 0; - int mContextEnd = 0; - float mX = 0f; - float mY = 0f; - boolean mRtl = false; - - public DrawTextRun(int textID, - int start, - int end, - int contextStart, - int contextEnd, - float x, - float y, - boolean rtl) { - mTextID = textID; - mStart = start; - mEnd = end; - mContextStart = contextStart; - mContextEnd = contextEnd; - mX = x; - mY = y; - mRtl = rtl; - } - - @Override - public void write(WireBuffer buffer) { - COMPANION.apply(buffer, mTextID, mStart, mEnd, mContextStart, mContextEnd, mX, mY, mRtl); - - } - - @Override - public String toString() { - return ""; - } - - public static class Companion implements CompanionOperation { - private Companion() { - } - - @Override - public void read(WireBuffer buffer, List<Operation> operations) { - int text = buffer.readInt(); - int start = buffer.readInt(); - int end = buffer.readInt(); - int contextStart = buffer.readInt(); - int contextEnd = buffer.readInt(); - float x = buffer.readFloat(); - float y = buffer.readFloat(); - boolean rtl = buffer.readBoolean(); - DrawTextRun op = new DrawTextRun(text, start, end, contextStart, contextEnd, x, y, rtl); - - operations.add(op); - } - - @Override - public String name() { - return ""; - } - - @Override - public int id() { - return 0; - } - - public void apply(WireBuffer buffer, - int textID, - int start, - int end, - int contextStart, - int contextEnd, - float x, - float y, - boolean rtl) { - buffer.start(Operations.DRAW_TEXT_RUN); - buffer.writeInt(textID); - buffer.writeInt(start); - buffer.writeInt(end); - buffer.writeInt(contextStart); - buffer.writeInt(contextEnd); - buffer.writeFloat(x); - buffer.writeFloat(y); - buffer.writeBoolean(rtl); - } - } - - @Override - public void paint(PaintContext context) { - context.drawTextRun(mTextID, mStart, mEnd, mContextStart, mContextEnd, mX, mY, mRtl); - } -} diff --git a/core/java/com/android/internal/widget/remotecompose/core/operations/IntegerExpression.java b/core/java/com/android/internal/widget/remotecompose/core/operations/IntegerExpression.java new file mode 100644 index 000000000000..d52df5d2bcea --- /dev/null +++ b/core/java/com/android/internal/widget/remotecompose/core/operations/IntegerExpression.java @@ -0,0 +1,177 @@ +/* + * Copyright (C) 2024 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package com.android.internal.widget.remotecompose.core.operations; + +import com.android.internal.widget.remotecompose.core.CompanionOperation; +import com.android.internal.widget.remotecompose.core.Operation; +import com.android.internal.widget.remotecompose.core.Operations; +import com.android.internal.widget.remotecompose.core.RemoteContext; +import com.android.internal.widget.remotecompose.core.VariableSupport; +import com.android.internal.widget.remotecompose.core.WireBuffer; +import com.android.internal.widget.remotecompose.core.operations.utilities.IntegerExpressionEvaluator; + +import java.util.Arrays; +import java.util.List; + +/** + * Operation to deal with AnimatedFloats + * This is designed to be an optimized calculation for things like + * injecting the width of the component int draw rect + * As well as supporting generalized animation floats. + * The floats represent a RPN style calculator + */ +public class IntegerExpression implements Operation, VariableSupport { + public int mId; + private int mMask; + private int mPreMask; + public int[] mSrcValue; + public int[] mPreCalcValue; + private float mLastChange = Float.NaN; + public static final Companion COMPANION = new Companion(); + public static final int MAX_STRING_SIZE = 4000; + IntegerExpressionEvaluator mExp = new IntegerExpressionEvaluator(); + + public IntegerExpression(int id, int mask, int[] value) { + this.mId = id; + this.mMask = mask; + this.mSrcValue = value; + } + + @Override + public void updateVariables(RemoteContext context) { + if (mPreCalcValue == null || mPreCalcValue.length != mSrcValue.length) { + mPreCalcValue = new int[mSrcValue.length]; + } + mPreMask = mMask; + for (int i = 0; i < mSrcValue.length; i++) { + if (isId(mMask, i, mSrcValue[i])) { + mPreMask &= ~(0x1 << i); + mPreCalcValue[i] = context.getInteger(mSrcValue[i]); + } else { + mPreCalcValue[i] = mSrcValue[i]; + } + } + } + + + @Override + public void registerListening(RemoteContext context) { + for (int i = 0; i < mSrcValue.length; i++) { + if (isId(mMask, i, mSrcValue[i])) { + context.listensTo(mSrcValue[i], this); + } + } + } + + @Override + public void apply(RemoteContext context) { + updateVariables(context); + float t = context.getAnimationTime(); + if (Float.isNaN(mLastChange)) { + mLastChange = t; + } + int v = mExp.eval(mPreMask, Arrays.copyOf(mPreCalcValue, mPreCalcValue.length)); + context.loadInteger(mId, v); + } + + @Override + public void write(WireBuffer buffer) { + COMPANION.apply(buffer, mId, mMask, mSrcValue); + } + + @Override + public String toString() { + StringBuilder s = new StringBuilder(); + for (int i = 0; i < mPreCalcValue.length; i++) { + if (i != 0) { + s.append(" "); + } + if (IntegerExpressionEvaluator.isOperation(mMask, i)) { + if (isId(mMask, i, mSrcValue[i])) { + s.append("[" + mSrcValue[i] + "]"); + } else { + s.append(IntegerExpressionEvaluator.toMathName(mPreCalcValue[i])); + } + } else { + s.append(mSrcValue[i]); + } + } + return "IntegerExpression[" + mId + "] = (" + s + ")"; + } + + public static class Companion implements CompanionOperation { + private Companion() { + } + + @Override + public String name() { + return "FloatExpression"; + } + + @Override + public int id() { + return Operations.INTEGER_EXPRESSION; + } + + /** + * Writes out the operation to the buffer + * + * @param buffer + * @param id + * @param mask + * @param value + */ + public void apply(WireBuffer buffer, int id, int mask, int[] value) { + buffer.start(Operations.INTEGER_EXPRESSION); + buffer.writeInt(id); + buffer.writeInt(mask); + buffer.writeInt(value.length); + for (int i = 0; i < value.length; i++) { + buffer.writeInt(value[i]); + } + } + + @Override + public void read(WireBuffer buffer, List<Operation> operations) { + int id = buffer.readInt(); + int mask = buffer.readInt(); + int len = buffer.readInt(); + + int[] values = new int[len]; + for (int i = 0; i < values.length; i++) { + values[i] = buffer.readInt(); + } + + operations.add(new IntegerExpression(id, mask, values)); + } + } + + @Override + public String deepToString(String indent) { + return indent + toString(); + } + + /** + * given the "i" position in the mask is this an ID + * @param mask 32 bit mask used for defining numbers vs other + * @param i the bit in question + * @param value the value + * @return true if this is an ID + */ + public static boolean isId(int mask, int i, int value) { + return ((1 << i) & mask) != 0 && value < IntegerExpressionEvaluator.OFFSET; + } +} diff --git a/core/java/com/android/internal/widget/remotecompose/core/operations/Utils.java b/core/java/com/android/internal/widget/remotecompose/core/operations/Utils.java index fcb3bfaca503..e9b0c3b11044 100644 --- a/core/java/com/android/internal/widget/remotecompose/core/operations/Utils.java +++ b/core/java/com/android/internal/widget/remotecompose/core/operations/Utils.java @@ -40,7 +40,7 @@ public class Utils { * @param n * @return */ - static String trimString(String str, int n) { + public static String trimString(String str, int n) { if (str.length() > n) { str = str.substring(0, n - 3) + "..."; } @@ -55,6 +55,9 @@ public class Utils { */ public static String floatToString(float idvalue, float value) { if (Float.isNaN(idvalue)) { + if (idFromNan(value) == 0) { + return "NaN"; + } return "[" + idFromNan(idvalue) + "]" + floatToString(value); } return floatToString(value); @@ -67,6 +70,9 @@ public class Utils { */ public static String floatToString(float value) { if (Float.isNaN(value)) { + if (idFromNan(value) == 0) { + return "NaN"; + } return "[" + idFromNan(value) + "]"; } return Float.toString(value); @@ -107,6 +113,7 @@ public class Utils { public static boolean isVariable(float v) { if (Float.isNaN(v)) { int id = idFromNan(v); + if (id == 0) return false; return id > 40 || id < 10; } return false; @@ -222,6 +229,4 @@ public class Utils { } return 0; } - - } diff --git a/core/java/com/android/internal/widget/remotecompose/core/operations/paint/Painter.java b/core/java/com/android/internal/widget/remotecompose/core/operations/paint/Painter.java new file mode 100644 index 000000000000..ada3757bd4ca --- /dev/null +++ b/core/java/com/android/internal/widget/remotecompose/core/operations/paint/Painter.java @@ -0,0 +1,260 @@ +/* + * Copyright (C) 2023 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package com.android.internal.widget.remotecompose.core.operations.paint; + + +/** + * Provides a Builder pattern for a PaintBundle + */ +class Painter { + PaintBundle mPaint; + + /** + * Write the paint to the buffer + */ + public PaintBundle commit() { + return mPaint; + } + + public Painter setAntiAlias(boolean aa) { + mPaint.setAntiAlias(aa); + return this; + } + + public Painter setColor(int color) { + mPaint.setColor(color); + return this; + } + + public Painter setColorId(int colorId) { + mPaint.setColorId(colorId); + return this; + } + + /** + * Set the paint's Join. + * + * @param join set the paint's Join, used whenever the paint's style is + * Stroke or StrokeAndFill. + */ + public Painter setStrokeJoin(int join) { + mPaint.setStrokeJoin(join); + return this; + } + + /** + * Set the width for stroking. Pass 0 to stroke in hairline mode. + * Hairlines always draws a single + * pixel independent of the canvas's matrix. + * + * @param width set the paint's stroke width, used whenever the paint's + * style is Stroke or StrokeAndFill. + */ + public Painter setStrokeWidth(float width) { + mPaint.setStrokeWidth(width); + return this; + } + + /** + * Set the paint's style, used for controlling how primitives' geometries + * are interpreted (except for drawBitmap, which always assumes Fill). + * + * @param style The new style to set in the paint + */ + public Painter setStyle(int style) { + mPaint.setStyle(style); + return this; + } + + /** + * Set the paint's Cap. + * + * @param cap set the paint's line cap style, used whenever the paint's + * style is Stroke or StrokeAndFill. + */ + public Painter setStrokeCap(int cap) { + mPaint.setStrokeCap(cap); + return this; + } + + /** + * Set the paint's stroke miter value. This is used to control the behavior + * of miter joins when the joins angle is sharp. This value must be >= 0. + * + * @param miter set the miter limit on the paint, used whenever the paint's + * style is Stroke or StrokeAndFill. + */ + public Painter setStrokeMiter(float miter) { + mPaint.setStrokeMiter(miter); + return this; + } + + /** + * Helper to setColor(), that only assigns the color's alpha value, + * leaving its r,g,b values unchanged. Results are undefined if the alpha + * value is outside of the range [0..1.0] + * + * @param alpha set the alpha component [0..1.0] of the paint's color. + */ + public Painter setAlpha(float alpha) { + mPaint.setAlpha((alpha > 2) ? alpha / 255f : alpha); + return this; + } + + /** + * Create a color filter that uses the specified color and Porter-Duff mode. + * + * @param color The ARGB source color used with the specified Porter-Duff + * mode + * @param mode The porter-duff mode that is applied + */ + public Painter setPorterDuffColorFilter(int color, int mode) { + mPaint.setColorFilter(color, mode); + return this; + } + + /** + * sets a shader that draws a linear gradient along a line. + * + * @param startX The x-coordinate for the start of the gradient line + * @param startY The y-coordinate for the start of the gradient line + * @param endX The x-coordinate for the end of the gradient line + * @param endY The y-coordinate for the end of the gradient line + * @param colors The sRGB colors to be distributed along the gradient + * line + * @param positions May be null. The relative positions [0..1] of each + * corresponding color in the colors array. If this is null, + * the colors are distributed evenly along the gradient + * line. + * @param tileMode The Shader tiling mode + */ + public Painter setLinearGradient( + float startX, + float startY, + float endX, + float endY, + int[] colors, + float[] positions, + int tileMode + ) { + mPaint.setLinearGradient(colors, positions, startX, + startY, endX, endY, tileMode); + return this; + } + + /** + * Sets a shader that draws a radial gradient given the center and radius. + * + * @param centerX The x-coordinate of the center of the radius + * @param centerY The y-coordinate of the center of the radius + * @param radius Must be positive. The radius of the circle for this + * gradient. + * @param colors The sRGB colors to be distributed between the center + * and edge of the circle + * @param positions May be <code>null</code>. Valid values are between + * <code>0.0f</code> and + * <code>1.0f</code>. The relative position of each + * corresponding color in the colors array. If + * <code>null</code>, colors are distributed evenly + * between the center and edge of the circle. + * @param tileMode The Shader tiling mode + */ + public Painter setRadialGradient( + float centerX, + float centerY, + float radius, + int[] colors, + float[] positions, + int tileMode + ) { + mPaint.setRadialGradient(colors, positions, centerX, + centerY, radius, tileMode); + return this; + } + + /** + * Set a shader that draws a sweep gradient around a center point. + * + * @param centerX The x-coordinate of the center + * @param centerY The y-coordinate of the center + * @param colors The sRGB colors to be distributed between around the + * center. There must be at least 2 colors in the array. + * @param positions May be NULL. The relative position of each corresponding + * color in the colors array, beginning with 0 and ending + * with 1.0. If the values are not monotonic, the drawing + * may produce unexpected results. If positions is NULL, + * then the colors are automatically spaced evenly. + */ + public Painter setSweepGradient( + float centerX, + float centerY, + int[] colors, + float[] positions + ) { + mPaint.setSweepGradient(colors, positions, centerX, centerY); + return this; + } + + /** + * Set the paint's text size. This value must be > 0 + * + * @param size set the paint's text size in pixel units. + */ + public Painter setTextSize(float size) { + mPaint.setTextSize(size); + return this; + } + + /** + * sets a typeface object that best matches the specified existing + * typeface and the specified weight and italic style + * + * <p>Below are numerical values and corresponding common weight names.</p> + * <table> <thead> + * <tr><th>Value</th><th>Common weight name</th></tr> </thead> <tbody> + * <tr><td>100</td><td>Thin</td></tr> + * <tr><td>200</td><td>Extra Light</td></tr> + * <tr><td>300</td><td>Light</td></tr> + * <tr><td>400</td><td>Normal</td></tr> + * <tr><td>500</td><td>Medium</td></tr> + * <tr><td>600</td><td>Semi Bold</td></tr> + * <tr><td>700</td><td>Bold</td></tr> + * <tr><td>800</td><td>Extra Bold</td></tr> + * <tr><td>900</td><td>Black</td></tr> </tbody> </table> + * + * @param fontType 0 = default 1 = sans serif 2 = serif 3 = monospace + * @param weight The desired weight to be drawn. + * @param italic {@code true} if italic style is desired to be drawn. + * Otherwise, {@code false} + */ + public Painter setTypeface(int fontType, int weight, boolean italic) { + mPaint.setTextStyle(fontType, weight, italic); + return this; + } + + + public Painter setFilterBitmap(boolean filter) { + mPaint.setFilterBitmap(filter); + return this; + } + + + public Painter setShader(int id) { + mPaint.setShader(id); + return this; + } + +} diff --git a/core/java/com/android/internal/widget/remotecompose/core/operations/utilities/IntFloatMap.java b/core/java/com/android/internal/widget/remotecompose/core/operations/utilities/IntFloatMap.java new file mode 100644 index 000000000000..23c3ec593b3c --- /dev/null +++ b/core/java/com/android/internal/widget/remotecompose/core/operations/utilities/IntFloatMap.java @@ -0,0 +1,140 @@ +/* + * Copyright (C) 2023 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package com.android.internal.widget.remotecompose.core.operations.utilities; + +import java.util.Arrays; + +public class IntFloatMap { + + private static final int DEFAULT_CAPACITY = 16; + private static final float LOAD_FACTOR = 0.75f; + private static final int NOT_PRESENT = Integer.MIN_VALUE; + private int[] mKeys; + private float[] mValues; + int mSize; + + public IntFloatMap() { + mKeys = new int[DEFAULT_CAPACITY]; + Arrays.fill(mKeys, NOT_PRESENT); + mValues = new float[DEFAULT_CAPACITY]; + } + + /** + * clear the map + */ + public void clear() { + Arrays.fill(mKeys, NOT_PRESENT); + Arrays.fill(mValues, Float.NaN); // not strictly necessary but defensive + mSize = 0; + } + + /** + * is the key contained in map + * + * @param key the key to check + * @return true if the map contains the key + */ + public boolean contains(int key) { + return findKey(key) != -1; + } + + /** + * Put a item in the map + * + * @param key item'values key + * @param value item's value + * @return old value if exist + */ + public float put(int key, float value) { + if (key == NOT_PRESENT) { + throw new IllegalArgumentException("Key cannot be NOT_PRESENT"); + } + if (mSize > mKeys.length * LOAD_FACTOR) { + resize(); + } + return insert(key, value); + } + + /** + * get an element given the key + * + * @param key the key to fetch + * @return the value + */ + public float get(int key) { + int index = findKey(key); + if (index == -1) { + return 0; + } else + return mValues[index]; + } + + /** + * how many elements in the map + * + * @return number of elements + */ + public int size() { + return mSize; + } + + private float insert(int key, float value) { + int index = hash(key) % mKeys.length; + while (mKeys[index] != NOT_PRESENT && mKeys[index] != key) { + index = (index + 1) % mKeys.length; + } + float oldValue = 0; + if (mKeys[index] == NOT_PRESENT) { + mSize++; + } else { + oldValue = mValues[index]; + } + mKeys[index] = key; + mValues[index] = value; + return oldValue; + } + + private int findKey(int key) { + int index = hash(key) % mKeys.length; + while (mKeys[index] != NOT_PRESENT) { + if (mKeys[index] == key) { + return index; + } + index = (index + 1) % mKeys.length; + } + return -1; + } + + private int hash(int key) { + return key; + } + + private void resize() { + int[] oldKeys = mKeys; + float[] oldValues = mValues; + mKeys = new int[(oldKeys.length * 2)]; + for (int i = 0; i < mKeys.length; i++) { + mKeys[i] = NOT_PRESENT; + } + mValues = new float[oldKeys.length * 2]; + mSize = 0; + for (int i = 0; i < oldKeys.length; i++) { + if (oldKeys[i] != NOT_PRESENT) { + put(oldKeys[i], oldValues[i]); + } + } + } +} diff --git a/core/java/com/android/internal/widget/remotecompose/core/operations/utilities/IntIntMap.java b/core/java/com/android/internal/widget/remotecompose/core/operations/utilities/IntIntMap.java new file mode 100644 index 000000000000..221014c9049e --- /dev/null +++ b/core/java/com/android/internal/widget/remotecompose/core/operations/utilities/IntIntMap.java @@ -0,0 +1,139 @@ +/* + * Copyright (C) 2023 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package com.android.internal.widget.remotecompose.core.operations.utilities; + +import java.util.Arrays; + +public class IntIntMap { + private static final int DEFAULT_CAPACITY = 16; + private static final float LOAD_FACTOR = 0.75f; + private static final int NOT_PRESENT = Integer.MIN_VALUE; + private int[] mKeys; + private int[] mValues; + int mSize; + + public IntIntMap() { + mKeys = new int[DEFAULT_CAPACITY]; + Arrays.fill(mKeys, NOT_PRESENT); + mValues = new int[DEFAULT_CAPACITY]; + } + + /** + * clear the map + */ + public void clear() { + Arrays.fill(mKeys, NOT_PRESENT); + Arrays.fill(mValues, 0); + mSize = 0; + } + + /** + * is the key contained in map + * + * @param key the key to check + * @return true if the map contains the key + */ + public boolean contains(int key) { + return findKey(key) != -1; + } + + /** + * Put a item in the map + * + * @param key item'values key + * @param value item's value + * @return old value if exist + */ + public int put(int key, int value) { + if (key == NOT_PRESENT) { + throw new IllegalArgumentException("Key cannot be NOT_PRESENT"); + } + if (mSize > mKeys.length * LOAD_FACTOR) { + resize(); + } + return insert(key, value); + } + + /** + * get an element given the key + * + * @param key the key to fetch + * @return the value + */ + public int get(int key) { + int index = findKey(key); + if (index == -1) { + return 0; + } else + return mValues[index]; + } + + /** + * how many elements in the map + * + * @return number of elements + */ + public int size() { + return mSize; + } + + private int insert(int key, int value) { + int index = hash(key) % mKeys.length; + while (mKeys[index] != NOT_PRESENT && mKeys[index] != key) { + index = (index + 1) % mKeys.length; + } + int oldValue = 0; + if (mKeys[index] == NOT_PRESENT) { + mSize++; + } else { + oldValue = mValues[index]; + } + mKeys[index] = key; + mValues[index] = value; + return oldValue; + } + + private int findKey(int key) { + int index = hash(key) % mKeys.length; + while (mKeys[index] != NOT_PRESENT) { + if (mKeys[index] == key) { + return index; + } + index = (index + 1) % mKeys.length; + } + return -1; + } + + private int hash(int key) { + return key; + } + + private void resize() { + int[] oldKeys = mKeys; + int[] oldValues = mValues; + mKeys = new int[(oldKeys.length * 2)]; + for (int i = 0; i < mKeys.length; i++) { + mKeys[i] = NOT_PRESENT; + } + mValues = new int[oldKeys.length * 2]; + mSize = 0; + for (int i = 0; i < oldKeys.length; i++) { + if (oldKeys[i] != NOT_PRESENT) { + put(oldKeys[i], oldValues[i]); + } + } + } +} diff --git a/core/java/com/android/internal/widget/remotecompose/core/operations/utilities/IntegerExpressionEvaluator.java b/core/java/com/android/internal/widget/remotecompose/core/operations/utilities/IntegerExpressionEvaluator.java new file mode 100644 index 000000000000..4c1389c5a7df --- /dev/null +++ b/core/java/com/android/internal/widget/remotecompose/core/operations/utilities/IntegerExpressionEvaluator.java @@ -0,0 +1,429 @@ +/* + * Copyright (C) 2024 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package com.android.internal.widget.remotecompose.core.operations.utilities; + +/** + * High performance Integer expression evaluator + */ +public class IntegerExpressionEvaluator { + static IntMap<String> sNames = new IntMap<>(); + public static final int OFFSET = 0x10000; + // add, sub, mul,div,mod,min,max, shl, shr, ushr, OR, AND , XOR, COPY_SIGN + public static final int I_ADD = OFFSET + 1; + public static final int I_SUB = OFFSET + 2; + public static final int I_MUL = OFFSET + 3; + public static final int I_DIV = OFFSET + 4; + public static final int I_MOD = OFFSET + 5; + public static final int I_SHL = OFFSET + 6; + public static final int I_SHR = OFFSET + 7; + public static final int I_USHR = OFFSET + 8; + public static final int I_OR = OFFSET + 9; + public static final int I_AND = OFFSET + 10; + public static final int I_XOR = OFFSET + 11; + public static final int I_COPY_SIGN = OFFSET + 12; + public static final int I_MIN = OFFSET + 13; + public static final int I_MAX = OFFSET + 14; + + public static final int I_NEG = OFFSET + 15; + public static final int I_ABS = OFFSET + 16; + public static final int I_INCR = OFFSET + 17; + public static final int I_DECR = OFFSET + 18; + public static final int I_NOT = OFFSET + 19; + public static final int I_SIGN = OFFSET + 20; + + public static final int I_CLAMP = OFFSET + 21; + public static final int I_IFELSE = OFFSET + 22; + public static final int I_MAD = OFFSET + 23; + + public static final float LAST_OP = 24; + + public static final int I_VAR1 = OFFSET + 24; + public static final int I_VAR2 = OFFSET + 24; + + + int[] mStack; + int[] mLocalStack = new int[128]; + int[] mVar; + + + interface Op { + int eval(int sp); + } + + /** + * Evaluate a float expression + * + * @param exp + * @param var + * @return + */ + public int eval(int mask, int[] exp, int... var) { + mStack = exp; + mVar = var; + int sp = -1; + for (int i = 0; i < mStack.length; i++) { + int v = mStack[i]; + if (((1 << i) & mask) != 0) { + sp = mOps[v - OFFSET].eval(sp); + } else { + mStack[++sp] = v; + } + } + return mStack[sp]; + } + + /** + * Evaluate a int expression + * + * @param exp + * @param len + * @param var + * @return + */ + public int eval(int mask, int[] exp, int len, int... var) { + System.arraycopy(exp, 0, mLocalStack, 0, len); + mStack = mLocalStack; + mVar = var; + int sp = -1; + for (int i = 0; i < len; i++) { + int v = mStack[i]; + if (((1 << i) & mask) != 0) { + sp = mOps[v - OFFSET].eval(sp); + } else { + mStack[++sp] = v; + } + } + return mStack[sp]; + } + + /** + * Evaluate a int expression + * + * @param exp + * @param var + * @return + */ + public int evalDB(int mask, int[] exp, int... var) { + mStack = exp; + mVar = var; + int sp = -1; + for (int i = 0; i < exp.length; i++) { + int v = mStack[i]; + if (((1 << i) & mask) != 0) { + System.out.print(" " + sNames.get((v - OFFSET))); + sp = mOps[v - OFFSET].eval(sp); + } else { + System.out.print(" " + v); + mStack[++sp] = v; + } + } + return mStack[sp]; + } + + Op[] mOps = { + null, + (sp) -> { // ADD + mStack[sp - 1] = mStack[sp - 1] + mStack[sp]; + return sp - 1; + }, + (sp) -> { // SUB + mStack[sp - 1] = mStack[sp - 1] - mStack[sp]; + return sp - 1; + }, + (sp) -> { // MUL + mStack[sp - 1] = mStack[sp - 1] * mStack[sp]; + return sp - 1; + }, + (sp) -> { // DIV + mStack[sp - 1] = mStack[sp - 1] / mStack[sp]; + return sp - 1; + }, + (sp) -> { // MOD + mStack[sp - 1] = mStack[sp - 1] % mStack[sp]; + return sp - 1; + }, + (sp) -> { // SHL shift left + mStack[sp - 1] = mStack[sp - 1] << mStack[sp]; + return sp - 1; + }, + (sp) -> { // SHR shift right + mStack[sp - 1] = mStack[sp - 1] >> mStack[sp]; + return sp - 1; + }, + (sp) -> { // USHR unsigned shift right + mStack[sp - 1] = mStack[sp - 1] >>> mStack[sp]; + return sp - 1; + }, + (sp) -> { // OR operator + mStack[sp - 1] = mStack[sp - 1] | mStack[sp]; + return sp - 1; + }, + (sp) -> { // AND operator + mStack[sp - 1] = mStack[sp - 1] & mStack[sp]; + return sp - 1; + }, + (sp) -> { // XOR xor operator + mStack[sp - 1] = mStack[sp - 1] ^ mStack[sp]; + return sp - 1; + }, + (sp) -> { // COPY_SIGN copy the sing of (using bit magic) + mStack[sp - 1] = (mStack[sp - 1] ^ (mStack[sp] >> 31)) + - (mStack[sp] >> 31); + return sp - 1; + }, + (sp) -> { // MIN + mStack[sp - 1] = Math.min(mStack[sp - 1], mStack[sp]); + return sp - 1; + }, + (sp) -> { // MAX + mStack[sp - 1] = Math.max(mStack[sp - 1], mStack[sp]); + return sp - 1; + }, + (sp) -> { // NEG + mStack[sp] = -mStack[sp]; + return sp; + }, + (sp) -> { // ABS + mStack[sp] = Math.abs(mStack[sp]); + return sp; + }, + (sp) -> { // INCR increment + mStack[sp] = mStack[sp] + 1; + return sp; + }, + (sp) -> { // DECR decrement + mStack[sp] = mStack[sp] - 1; + return sp; + }, + (sp) -> { // NOT Bit invert + mStack[sp] = ~mStack[sp]; + return sp; + }, + (sp) -> { // SIGN x<0 = -1,x==0 = 0 , x>0 = 1 + mStack[sp] = (mStack[sp] >> 31) | (-mStack[sp] >>> 31); + return sp; + }, + + (sp) -> { // CLAMP(min,max, val) + mStack[sp - 2] = Math.min(Math.max(mStack[sp - 2], mStack[sp]), + mStack[sp - 1]); + return sp - 2; + }, + (sp) -> { // Ternary conditional + mStack[sp - 2] = (mStack[sp] > 0) + ? mStack[sp - 1] : mStack[sp - 2]; + return sp - 2; + }, + (sp) -> { // MAD + mStack[sp - 2] = mStack[sp] + mStack[sp - 1] * mStack[sp - 2]; + return sp - 2; + }, + + (sp) -> { // first var = + mStack[sp] = mVar[0]; + return sp; + }, + (sp) -> { // second var y? + mStack[sp] = mVar[1]; + return sp; + }, + (sp) -> { // 3rd var z? + mStack[sp] = mVar[2]; + return sp; + }, + }; + + static { + int k = 0; + sNames.put(k++, "NOP"); + sNames.put(k++, "+"); + sNames.put(k++, "-"); + sNames.put(k++, "*"); + sNames.put(k++, "/"); + sNames.put(k++, "%"); + sNames.put(k++, "<<"); + sNames.put(k++, ">>"); + sNames.put(k++, ">>>"); + sNames.put(k++, "|"); + sNames.put(k++, "&"); + sNames.put(k++, "^"); + sNames.put(k++, "copySign"); + sNames.put(k++, "min"); + sNames.put(k++, "max"); + sNames.put(k++, "neg"); + sNames.put(k++, "abs"); + sNames.put(k++, "incr"); + sNames.put(k++, "decr"); + sNames.put(k++, "not"); + sNames.put(k++, "sign"); + sNames.put(k++, "clamp"); + sNames.put(k++, "ifElse"); + sNames.put(k++, "mad"); + sNames.put(k++, "ceil"); + sNames.put(k++, "a[0]"); + sNames.put(k++, "a[1]"); + sNames.put(k++, "a[2]"); + } + + /** + * given a int command return its math name (e.g sin, cos etc.) + * + * @param f + * @return + */ + public static String toMathName(int f) { + int id = f - OFFSET; + return sNames.get(id); + } + + /** + * Convert an expression encoded as an array of ints int ot a string + * + * @param exp + * @param labels + * @return + */ + public static String toString(int mask, int[] exp, String[] labels) { + StringBuilder s = new StringBuilder(); + for (int i = 0; i < exp.length; i++) { + int v = exp[i]; + + if (((1 << i) & mask) != 0) { + if (v < OFFSET) { + s.append(toMathName(v)); + } else { + s.append("["); + s.append(v); + s.append("]"); + } + } else { + if (labels[i] != null) { + s.append(labels[i]); + } + s.append(v); + } + s.append(" "); + } + return s.toString(); + } + + /** + * Convert an expression encoded as an array of ints int ot a string + * + * @param mask bit mask of operators vs commands + * @param exp + * @return + */ + public static String toString(int mask, int[] exp) { + StringBuilder s = new StringBuilder(); + s.append(Integer.toBinaryString(mask)); + s.append(" : "); + for (int i = 0; i < exp.length; i++) { + int v = exp[i]; + + if (((1 << i) & mask) != 0) { + if (v > OFFSET) { + s.append(" "); + s.append(toMathName(v)); + s.append(" "); + + } else { + s.append("["); + s.append(v); + s.append("]"); + } + } + s.append(" " + v); + } + return s.toString(); + } + + /** + * This creates an infix string expression + * @param mask The bits that are operators + * @param exp the array of expressions + * @return infix string + */ + public static String toStringInfix(int mask, int[] exp) { + return toString(mask, exp, exp.length - 1); + } + + static String toString(int mask, int[] exp, int sp) { + String[] str = new String[exp.length]; + if (((1 << sp) & mask) != 0) { + int id = exp[sp] - OFFSET; + switch (NO_OF_OPS[id]) { + case -1: + return "nop"; + case 1: + return sNames.get(id) + "(" + toString(mask, exp, sp - 1) + ") "; + case 2: + if (infix(id)) { + return "(" + toString(mask, exp, sp - 2) + + " " + sNames.get(id) + " " + + toString(mask, exp, sp - 1) + ") "; + } else { + return sNames.get(id) + "(" + + toString(mask, exp, sp - 2) + ", " + + toString(mask, exp, sp - 1) + ")"; + } + case 3: + if (infix(id)) { + return "((" + toString(mask, exp, sp + 3) + ") ? " + + toString(mask, exp, sp - 2) + ":" + + toString(mask, exp, sp - 1) + ")"; + } else { + return sNames.get(id) + + "(" + toString(mask, exp, sp - 3) + + ", " + toString(mask, exp, sp - 2) + + ", " + toString(mask, exp, sp - 1) + ")"; + } + } + } + return Integer.toString(exp[sp]); + } + + static final int[] NO_OF_OPS = { + -1, // no op + 2, 2, 2, 2, 2, // + - * / % + 2, 2, 2, 2, 2, 2, 2, 2, 2, //<<, >> , >>> , | , &, ^, min max + 1, 1, 1, 1, 1, 1, // neg, abs, ++, -- , not , sign + + 3, 3, 3, // clamp, ifElse, mad, + 0, 0, 0 // mad, ?:, + // a[0],a[1],a[2] + }; + + /** + * to be used by parser to determine if command is infix + * + * @param n the operator (minus the offset) + * @return true if the operator is infix + */ + static boolean infix(int n) { + return ((n < 12)); + } + + /** + * is it an id or operation + * @param mask the bits that mark elements as an operation + * @param i the bit to check + * @return true if the bit is 1 + */ + public static boolean isOperation(int mask, int i) { + return ((1 << i) & mask) != 0; + } +} diff --git a/core/java/com/android/internal/widget/remotecompose/core/types/BooleanConstant.java b/core/java/com/android/internal/widget/remotecompose/core/types/BooleanConstant.java new file mode 100644 index 000000000000..1051192441dd --- /dev/null +++ b/core/java/com/android/internal/widget/remotecompose/core/types/BooleanConstant.java @@ -0,0 +1,96 @@ +/* + * Copyright (C) 2024 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package com.android.internal.widget.remotecompose.core.types; + +import com.android.internal.widget.remotecompose.core.CompanionOperation; +import com.android.internal.widget.remotecompose.core.Operation; +import com.android.internal.widget.remotecompose.core.Operations; +import com.android.internal.widget.remotecompose.core.RemoteContext; +import com.android.internal.widget.remotecompose.core.WireBuffer; + +import java.util.List; + +/** + * Used to represent a boolean + */ +public class BooleanConstant implements Operation { + boolean mValue = false; + private int mId; + + public BooleanConstant(int id, boolean value) { + mId = id; + mValue = value; + } + + @Override + public void write(WireBuffer buffer) { + COMPANION.apply(buffer, mId, mValue); + } + + @Override + public void apply(RemoteContext context) { + + } + + @Override + public String deepToString(String indent) { + return toString(); + } + + @Override + public String toString() { + return "BooleanConstant[" + mId + "] = " + mValue + ""; + } + + public static final Companion COMPANION = new Companion(); + + public static class Companion implements CompanionOperation { + private Companion() { + } + + @Override + public String name() { + return "OrigamiBoolean"; + } + + @Override + public int id() { + return Operations.DATA_BOOLEAN; + } + + /** + * Writes out the operation to the buffer + * + * @param buffer + * @param id + * @param value + */ + public void apply(WireBuffer buffer, int id, boolean value) { + buffer.start(Operations.DATA_BOOLEAN); + buffer.writeInt(id); + buffer.writeBoolean(value); + } + + @Override + public void read(WireBuffer buffer, List<Operation> operations) { + int id = buffer.readInt(); + + boolean value = buffer.readBoolean(); + operations.add(new BooleanConstant(id, value)); + } + } + +} diff --git a/core/java/com/android/internal/widget/remotecompose/core/types/IntegerConstant.java b/core/java/com/android/internal/widget/remotecompose/core/types/IntegerConstant.java new file mode 100644 index 000000000000..ceb323629e98 --- /dev/null +++ b/core/java/com/android/internal/widget/remotecompose/core/types/IntegerConstant.java @@ -0,0 +1,96 @@ +/* + * Copyright (C) 2024 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package com.android.internal.widget.remotecompose.core.types; + +import com.android.internal.widget.remotecompose.core.CompanionOperation; +import com.android.internal.widget.remotecompose.core.Operation; +import com.android.internal.widget.remotecompose.core.Operations; +import com.android.internal.widget.remotecompose.core.RemoteContext; +import com.android.internal.widget.remotecompose.core.WireBuffer; + +import java.util.List; + +/** + * Represents a single integer typically used for states + * or named for input into the system + */ +public class IntegerConstant implements Operation { + private int mValue = 0; + private int mId; + + IntegerConstant(int id, int value) { + mId = id; + mValue = value; + } + + @Override + public void write(WireBuffer buffer) { + COMPANION.apply(buffer, mId, mValue); + } + + @Override + public void apply(RemoteContext context) { + context.loadInteger(mId, mValue); + } + + @Override + public String deepToString(String indent) { + return toString(); + } + + @Override + public String toString() { + return "IntegerConstant[" + mId + "] = " + mValue + ""; + } + + public static final Companion COMPANION = new Companion(); + + public static class Companion implements CompanionOperation { + private Companion() { + } + + @Override + public String name() { + return "IntegerConstant"; + } + + @Override + public int id() { + return Operations.DATA_INT; + } + + /** + * Writes out the operation to the buffer + * + * @param buffer + * @param textId + * @param value + */ + public void apply(WireBuffer buffer, int textId, int value) { + buffer.start(Operations.DATA_INT); + buffer.writeInt(textId); + buffer.writeInt(value); + } + + @Override + public void read(WireBuffer buffer, List<Operation> operations) { + int id = buffer.readInt(); + + int value = buffer.readInt(); + operations.add(new IntegerConstant(id, value)); + } + } +} diff --git a/core/java/com/android/internal/widget/remotecompose/player/RemoteComposePlayer.java b/core/java/com/android/internal/widget/remotecompose/player/RemoteComposePlayer.java index 73e94fa6ecf4..b2406bf69ec8 100644 --- a/core/java/com/android/internal/widget/remotecompose/player/RemoteComposePlayer.java +++ b/core/java/com/android/internal/widget/remotecompose/player/RemoteComposePlayer.java @@ -410,4 +410,3 @@ public class RemoteComposePlayer extends FrameLayout { } } } - diff --git a/core/java/com/android/internal/widget/remotecompose/player/platform/AndroidPaintContext.java b/core/java/com/android/internal/widget/remotecompose/player/platform/AndroidPaintContext.java index ecb68bb21fb3..39a770acbf97 100644 --- a/core/java/com/android/internal/widget/remotecompose/player/platform/AndroidPaintContext.java +++ b/core/java/com/android/internal/widget/remotecompose/player/platform/AndroidPaintContext.java @@ -39,12 +39,16 @@ import com.android.internal.widget.remotecompose.core.operations.Utils; import com.android.internal.widget.remotecompose.core.operations.paint.PaintBundle; import com.android.internal.widget.remotecompose.core.operations.paint.PaintChanges; +import java.util.ArrayList; +import java.util.List; + /** * An implementation of PaintContext for the Android Canvas. * This is used to play the RemoteCompose operations on Android. */ public class AndroidPaintContext extends PaintContext { Paint mPaint = new Paint(); + List<Paint> mPaintList = new ArrayList<>(); Canvas mCanvas; Rect mTmpRect = new Rect(); // use in calculation of bounds @@ -162,6 +166,16 @@ public class AndroidPaintContext extends PaintContext { } @Override + public void savePaint() { + mPaintList.add(new Paint(mPaint)); + } + + @Override + public void restorePaint() { + mPaint = mPaintList.remove(mPaintList.size() - 1); + } + + @Override public void drawRoundRect(float left, float top, float right, @@ -335,6 +349,11 @@ public class AndroidPaintContext extends PaintContext { return null; } + /** + * This applies paint changes to the current paint + * + * @param mPaintData the list change to the paint + */ @Override public void applyPaint(PaintBundle mPaintData) { mPaintData.applyPaintChange((PaintContext) this, new PaintChanges() { diff --git a/core/java/com/android/internal/widget/remotecompose/player/platform/AndroidRemoteContext.java b/core/java/com/android/internal/widget/remotecompose/player/platform/AndroidRemoteContext.java index dd43bd5d32a6..5a87c7083c9d 100644 --- a/core/java/com/android/internal/widget/remotecompose/player/platform/AndroidRemoteContext.java +++ b/core/java/com/android/internal/widget/remotecompose/player/platform/AndroidRemoteContext.java @@ -120,6 +120,11 @@ class AndroidRemoteContext extends RemoteContext { mRemoteComposeState.updateFloat(id, value); } + @Override + public void loadInteger(int id, int value) { + mRemoteComposeState.updateInteger(id, value); + } + @Override public void loadColor(int id, int color) { @@ -142,6 +147,11 @@ class AndroidRemoteContext extends RemoteContext { } @Override + public int getInteger(int id) { + return mRemoteComposeState.getInteger(id); + } + + @Override public int getColor(int id) { return mRemoteComposeState.getColor(id); } diff --git a/core/java/com/android/internal/widget/remotecompose/player/platform/FloatsToPath.java b/core/java/com/android/internal/widget/remotecompose/player/platform/FloatsToPath.java index 2d766f8da295..7a8542712cbf 100644 --- a/core/java/com/android/internal/widget/remotecompose/player/platform/FloatsToPath.java +++ b/core/java/com/android/internal/widget/remotecompose/player/platform/FloatsToPath.java @@ -58,7 +58,7 @@ public class FloatsToPath { break; case PathData.CONIC: { i += 3; - if (Build.VERSION.SDK_INT >= 34) { + if (Build.VERSION.SDK_INT >= 34) { // REMOVE IN PLATFORM path.conicTo( floatPath[i + 0], floatPath[i + 1], floatPath[i + 2], floatPath[i + 3], diff --git a/core/jni/android_media_AudioSystem.cpp b/core/jni/android_media_AudioSystem.cpp index 7c62615cdc42..638591f130ab 100644 --- a/core/jni/android_media_AudioSystem.cpp +++ b/core/jni/android_media_AudioSystem.cpp @@ -2292,7 +2292,7 @@ static jint nativeAudioMixToJavaAudioMixingRule(JNIEnv *env, const AudioMix &nAu criteria.mValue.mUsage); jMixMatchCriterion = env->NewObject(gAudioMixMatchCriterionClass, gAudioMixMatchCriterionAttrCstor, - jMixMatchCriterion, criteria.mRule); + jAudioAttributes, criteria.mRule); break; case RULE_MATCH_ATTRIBUTE_CAPTURE_PRESET: jAudioAttributes = env->NewObject(gAudioAttributesClass, gAudioAttributesCstor); @@ -2300,7 +2300,7 @@ static jint nativeAudioMixToJavaAudioMixingRule(JNIEnv *env, const AudioMix &nAu criteria.mValue.mSource); jMixMatchCriterion = env->NewObject(gAudioMixMatchCriterionClass, gAudioMixMatchCriterionAttrCstor, - jMixMatchCriterion, criteria.mRule); + jAudioAttributes, criteria.mRule); break; } env->CallBooleanMethod(jAudioMixMatchCriterionList, gArrayListMethods.add, diff --git a/core/jni/android_view_SurfaceControl.cpp b/core/jni/android_view_SurfaceControl.cpp index 9ce76583517b..0f531641903a 100644 --- a/core/jni/android_view_SurfaceControl.cpp +++ b/core/jni/android_view_SurfaceControl.cpp @@ -22,6 +22,7 @@ #include <android/graphics/properties.h> #include <android/graphics/region.h> #include <android/gui/BnWindowInfosReportedListener.h> +#include <android/gui/EdgeExtensionParameters.h> #include <android/gui/JankData.h> #include <android/hardware/display/IDeviceProductInfoConstants.h> #include <android/os/IInputConstants.h> @@ -799,6 +800,20 @@ static void nativeSetStretchEffect(JNIEnv* env, jclass clazz, jlong transactionO transaction->setStretchEffect(ctrl, stretch); } +static void nativeSetEdgeExtensionEffect(JNIEnv* env, jclass clazz, jlong transactionObj, + jlong nativeObj, jboolean leftEdge, jboolean rightEdge, + jboolean topEdge, jboolean bottomEdge) { + auto transaction = reinterpret_cast<SurfaceComposerClient::Transaction*>(transactionObj); + auto* const ctrl = reinterpret_cast<SurfaceControl*>(nativeObj); + + auto effect = gui::EdgeExtensionParameters(); + effect.extendLeft = leftEdge; + effect.extendRight = rightEdge; + effect.extendTop = topEdge; + effect.extendBottom = bottomEdge; + transaction->setEdgeExtensionEffect(ctrl, effect); +} + static void nativeSetFlags(JNIEnv* env, jclass clazz, jlong transactionObj, jlong nativeObject, jint flags, jint mask) { auto transaction = reinterpret_cast<SurfaceComposerClient::Transaction*>(transactionObj); @@ -2340,6 +2355,8 @@ static const JNINativeMethod sSurfaceControlMethods[] = { (void*)nativeSetBlurRegions }, {"nativeSetStretchEffect", "(JJFFFFFFFFFF)V", (void*) nativeSetStretchEffect }, + {"nativeSetEdgeExtensionEffect", "(JJZZZZ)V", + (void*) nativeSetEdgeExtensionEffect }, {"nativeSetShadowRadius", "(JJF)V", (void*)nativeSetShadowRadius }, {"nativeSetFrameRate", "(JJFII)V", diff --git a/core/proto/android/app/appexitinfo.proto b/core/proto/android/app/appexitinfo.proto index e560a944b94b..8ee79623eabf 100644 --- a/core/proto/android/app/appexitinfo.proto +++ b/core/proto/android/app/appexitinfo.proto @@ -20,7 +20,7 @@ option java_multiple_files = true; package android.app; import "frameworks/base/core/proto/android/privacy.proto"; -import "frameworks/proto_logging/stats/enums/app/app_enums.proto"; +import "frameworks/proto_logging/stats/enums/app_shared/app_enums.proto"; /** * An android.app.ApplicationExitInfo object. diff --git a/core/proto/android/app/appstartinfo.proto b/core/proto/android/app/appstartinfo.proto index c13753343ba8..8de54586ab73 100644 --- a/core/proto/android/app/appstartinfo.proto +++ b/core/proto/android/app/appstartinfo.proto @@ -20,7 +20,7 @@ option java_multiple_files = true; package android.app; import "frameworks/base/core/proto/android/privacy.proto"; -import "frameworks/proto_logging/stats/enums/app/app_enums.proto"; +import "frameworks/proto_logging/stats/enums/app_shared/app_enums.proto"; /** * An android.app.ApplicationStartInfo object. diff --git a/core/proto/android/server/activitymanagerservice.proto b/core/proto/android/server/activitymanagerservice.proto index 90069f111fe5..58f39a9208da 100644 --- a/core/proto/android/server/activitymanagerservice.proto +++ b/core/proto/android/server/activitymanagerservice.proto @@ -35,7 +35,7 @@ import "frameworks/base/core/proto/android/server/intentresolver.proto"; import "frameworks/base/core/proto/android/server/windowmanagerservice.proto"; import "frameworks/base/core/proto/android/util/common.proto"; import "frameworks/base/core/proto/android/privacy.proto"; -import "frameworks/proto_logging/stats/enums/app/app_enums.proto"; +import "frameworks/proto_logging/stats/enums/app_shared/app_enums.proto"; option java_multiple_files = true; diff --git a/core/proto/android/server/powermanagerservice.proto b/core/proto/android/server/powermanagerservice.proto index 593bbc6f5d0d..8fd5d7160261 100644 --- a/core/proto/android/server/powermanagerservice.proto +++ b/core/proto/android/server/powermanagerservice.proto @@ -26,7 +26,7 @@ import "frameworks/base/core/proto/android/os/worksource.proto"; import "frameworks/base/core/proto/android/providers/settings.proto"; import "frameworks/base/core/proto/android/server/wirelesschargerdetector.proto"; import "frameworks/base/core/proto/android/privacy.proto"; -import "frameworks/proto_logging/stats/enums/app/app_enums.proto"; +import "frameworks/proto_logging/stats/enums/app_shared/app_enums.proto"; import "frameworks/proto_logging/stats/enums/os/enums.proto"; import "frameworks/proto_logging/stats/enums/view/enums.proto"; diff --git a/core/res/res/drawable/tooltip_frame.xml b/core/res/res/drawable/tooltip_frame.xml index 14130c899e96..e2618cad1d15 100644 --- a/core/res/res/drawable/tooltip_frame.xml +++ b/core/res/res/drawable/tooltip_frame.xml @@ -17,5 +17,5 @@ <shape xmlns:android="http://schemas.android.com/apk/res/android" android:shape="rectangle"> <solid android:color="?attr/tooltipBackgroundColor" /> - <corners android:radius="@dimen/tooltip_corner_radius" /> -</shape>
\ No newline at end of file + <corners android:radius="?attr/tooltipCornerRadius" /> +</shape> diff --git a/core/res/res/layout/tooltip.xml b/core/res/res/layout/tooltip.xml index 376c5eb125f4..5b6799e23f85 100644 --- a/core/res/res/layout/tooltip.xml +++ b/core/res/res/layout/tooltip.xml @@ -27,10 +27,10 @@ android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_margin="@dimen/tooltip_margin" - android:paddingStart="@dimen/tooltip_horizontal_padding" - android:paddingEnd="@dimen/tooltip_horizontal_padding" - android:paddingTop="@dimen/tooltip_vertical_padding" - android:paddingBottom="@dimen/tooltip_vertical_padding" + android:paddingStart="?attr/tooltipHorizontalPadding" + android:paddingEnd="?attr/tooltipHorizontalPadding" + android:paddingTop="?attr/tooltipVerticalPadding" + android:paddingBottom="?attr/tooltipVerticalPadding" android:maxWidth="256dp" android:background="?android:attr/tooltipFrameBackground" android:textAppearance="@style/TextAppearance.Tooltip" diff --git a/core/res/res/values-ar/strings.xml b/core/res/res/values-ar/strings.xml index 732b81b2b2b7..b3538938c998 100644 --- a/core/res/res/values-ar/strings.xml +++ b/core/res/res/values-ar/strings.xml @@ -202,7 +202,7 @@ <string name="ssl_ca_cert_noti_managed" msgid="217337232273211674">"بواسطة <xliff:g id="MANAGING_DOMAIN">%s</xliff:g>"</string> <string name="work_profile_deleted" msgid="5891181538182009328">"تم حذف ملف العمل."</string> <string name="work_profile_deleted_details" msgid="3773706828364418016">"تطبيق المشرف لملف العمل مفقود أو تالف لذا تم حذف ملف العمل والبيانات ذات الصلة. اتصل بالمشرف للحصول على المساعدة."</string> - <string name="work_profile_deleted_description_dpm_wipe" msgid="2477244968924647232">"لم يعد ملفك الشخصي للعمل متاحًا على هذا الجهاز"</string> + <string name="work_profile_deleted_description_dpm_wipe" msgid="2477244968924647232">"لم يعد ملف العمل الخاص بك متاحًا على هذا الجهاز"</string> <string name="work_profile_deleted_reason_maximum_password_failure" msgid="1080323158315663167">"تم إجراء محاولات كثيرة جدًا لإدخال كلمة المرور"</string> <string name="device_ownership_relinquished" msgid="4080886992183195724">"تنازل المشرف عن الجهاز للاستخدام الشخصي"</string> <string name="private_space_deleted_by_admin" msgid="1484365588862066939">"تمت إزالة المساحة الخاصّة"</string> @@ -224,7 +224,7 @@ <string name="factory_reset_message" msgid="2657049595153992213">"تعذّر استخدام تطبيق المشرف. سيتم محو بيانات جهازك الآن.\n\nإذا كانت لديك أسئلة، اتصل بمشرف مؤسستك."</string> <string name="printing_disabled_by" msgid="3517499806528864633">"تم إيقاف الطباعة بواسطة <xliff:g id="OWNER_APP">%s</xliff:g>."</string> <string name="personal_apps_suspension_title" msgid="7561416677884286600">"تفعيل ملف العمل"</string> - <string name="personal_apps_suspension_text" msgid="6115455688932935597">"تم حظر تطبيقاتك الشخصية إلى أن تفعِّل ملفك الشخصي للعمل."</string> + <string name="personal_apps_suspension_text" msgid="6115455688932935597">"تم حظر تطبيقاتك الشخصية إلى أن تفعِّل ملف العمل الخاص بك."</string> <string name="personal_apps_suspension_soon_text" msgid="8123898693479590">"سيتم حظر التطبيقات الشخصية في <xliff:g id="DATE">%1$s</xliff:g> في <xliff:g id="TIME">%2$s</xliff:g>. لا يسمح مشرف تكنولوجيا المعلومات في مؤسستك بإيقاف ملف العمل أكثر من <xliff:g id="NUMBER">%3$d</xliff:g> يوم."</string> <string name="personal_apps_suspended_turn_profile_on" msgid="2758012869627513689">"تفعيل"</string> <string name="work_profile_telephony_paused_title" msgid="7690804479291839519">"المكالمات والرسائل غير مفعّلة"</string> @@ -701,12 +701,12 @@ <string name="fingerprint_icon_content_description" msgid="4741068463175388817">"رمز بصمة الإصبع"</string> <string name="device_unlock_notification_name" msgid="2632928999862915709">"فتح قفل الجهاز"</string> <string name="alternative_unlock_setup_notification_title" msgid="6241508547901933544">"تجربة طريقة أخرى لفتح القفل"</string> - <string name="alternative_face_setup_notification_content" msgid="3384959224091897331">"استخدِم ميزة \"فتح الجهاز بالتعرف على الوجه\" عندما لا يتم التعرف على بصمة إصبعك، مثلاً عندما تكون أصابعك مبتلة."</string> + <string name="alternative_face_setup_notification_content" msgid="3384959224091897331">"استخدِم ميزة \"فتح الجهاز ببصمة الوجه\" عندما لا يتم التعرف على بصمة إصبعك، مثلاً عندما تكون أصابعك مبتلة."</string> <string name="alternative_fp_setup_notification_content" msgid="7454096947415721639">"استخدِم ميزة \"فتح الجهاز ببصمة الإصبع\" عندما لا يتم التعرف على وجهك، مثلاً عند عدم وجود ضوء كافٍ."</string> - <string name="face_recalibrate_notification_name" msgid="7311163114750748686">"فتح الجهاز بالتعرف على الوجه"</string> - <string name="face_recalibrate_notification_title" msgid="2524791952735579082">"مشكلة متعلّقة بميزة \"فتح الجهاز بالتعرف على الوجه\""</string> + <string name="face_recalibrate_notification_name" msgid="7311163114750748686">"فتح الجهاز ببصمة الوجه"</string> + <string name="face_recalibrate_notification_title" msgid="2524791952735579082">"مشكلة متعلّقة بميزة \"فتح الجهاز ببصمة الوجه\""</string> <string name="face_recalibrate_notification_content" msgid="3064513770251355594">"انقر لحذف نموذج الوجه ثم أضِف نموذجًا لوجهك مرة أخرى."</string> - <string name="face_sensor_privacy_enabled" msgid="7407126963510598508">"لاستخدام ميزة \"فتح الجهاز بالتعرف على الوجه\"، عليك منح إذن "<b>"الوصول إلى الكاميرا"</b>" في الإعدادات > الخصوصية."</string> + <string name="face_sensor_privacy_enabled" msgid="7407126963510598508">"لاستخدام ميزة \"فتح الجهاز ببصمة الوجه\"، عليك منح إذن "<b>"الوصول إلى الكاميرا"</b>" في الإعدادات > الخصوصية."</string> <string name="fingerprint_recalibrate_notification_name" msgid="1414578431898579354">"فتح الجهاز ببصمة الإصبع"</string> <string name="fingerprint_recalibrate_notification_title" msgid="2406561052064558497">"لا يمكن استخدام مستشعر بصمات الإصبع"</string> <string name="fingerprint_recalibrate_notification_content" msgid="8519935717822194943">"يُرجى التواصل مع مقدِّم خدمات إصلاح."</string> @@ -740,19 +740,19 @@ <string-array name="face_acquired_vendor"> </string-array> <string name="face_error_hw_not_available" msgid="5085202213036026288">"يتعذّر التحقُّق من الوجه. الجهاز غير مُتاح."</string> - <string name="face_error_timeout" msgid="2598544068593889762">"جرِّب \"فتح الجهاز بالتعرف على الوجه\" مرة أخرى."</string> + <string name="face_error_timeout" msgid="2598544068593889762">"جرِّب \"فتح الجهاز ببصمة الوجه\" مرة أخرى."</string> <string name="face_error_no_space" msgid="5649264057026021723">"يتعذَّر تخزين بيانات الوجه الجديد. احذف الوجه القديم أولاً."</string> <string name="face_error_canceled" msgid="2164434737103802131">"تمّ إلغاء عملية مصادقة الوجه."</string> - <string name="face_error_user_canceled" msgid="5766472033202928373">"ألغى المستخدم ميزة \"فتح الجهاز بالتعرف على الوجه\"."</string> + <string name="face_error_user_canceled" msgid="5766472033202928373">"ألغى المستخدم ميزة \"فتح الجهاز ببصمة الوجه\"."</string> <string name="face_error_lockout" msgid="7864408714994529437">"تمّ إجراء محاولات كثيرة. أعِد المحاولة لاحقًا."</string> - <string name="face_error_lockout_permanent" msgid="8533257333130473422">"أجريت محاولات كثيرة جدًا. ميزة \"فتح الجهاز بالتعرف على الوجه\" غير متاحة."</string> + <string name="face_error_lockout_permanent" msgid="8533257333130473422">"أجريت محاولات كثيرة جدًا. ميزة \"فتح الجهاز ببصمة الوجه\" غير متاحة."</string> <string name="face_error_lockout_screen_lock" msgid="5062609811636860928">"تم إجراء عدد كبير جدًا من المحاولات. أدخِل قفل الشاشة بدلاً من ذلك."</string> <string name="face_error_unable_to_process" msgid="5723292697366130070">"يتعذّر التحقق من الوجه. حاول مرة أخرى."</string> - <string name="face_error_not_enrolled" msgid="1134739108536328412">"لم يسبق لك إعداد ميزة \"فتح الجهاز بالتعرف على الوجه\"."</string> - <string name="face_error_hw_not_present" msgid="7940978724978763011">"ميزة \"فتح الجهاز بالتعرف على الوجه\" غير متوافقة على هذا الجهاز."</string> + <string name="face_error_not_enrolled" msgid="1134739108536328412">"لم يسبق لك إعداد ميزة \"فتح الجهاز ببصمة الوجه\"."</string> + <string name="face_error_hw_not_present" msgid="7940978724978763011">"ميزة \"فتح الجهاز ببصمة الوجه\" غير متوافقة على هذا الجهاز."</string> <string name="face_error_security_update_required" msgid="5076017208528750161">"تم إيقاف جهاز الاستشعار مؤقتًا."</string> <string name="face_name_template" msgid="3877037340223318119">"الوجه <xliff:g id="FACEID">%d</xliff:g>"</string> - <string name="face_app_setting_name" msgid="5854024256907828015">"فتح الجهاز بالتعرف على الوجه"</string> + <string name="face_app_setting_name" msgid="5854024256907828015">"فتح الجهاز ببصمة الوجه"</string> <string name="face_or_screen_lock_app_setting_name" msgid="1603149075605709106">"استخدام ميزة \"فتح الجهاز بالتعرف على الوجه\" أو ميزة \"قفل الشاشة\""</string> <string name="face_dialog_default_subtitle" msgid="6620492813371195429">"استخدِم الوجه للمتابعة"</string> <string name="face_or_screen_lock_dialog_default_subtitle" msgid="5006381531158341844">"استخدام ميزة \"فتح القفل بالوجه\" أو ميزة \"قفل الشاشة\" للمتابعة"</string> @@ -1007,7 +1007,7 @@ <string name="lockscreen_pattern_wrong" msgid="2940138714468358458">"أعد المحاولة"</string> <string name="lockscreen_password_wrong" msgid="8605355913868947490">"أعد المحاولة"</string> <string name="lockscreen_storage_locked" msgid="634993789186443380">"فتح القفل للوصول إلى جميع الميزات والبيانات"</string> - <string name="faceunlock_multiple_failures" msgid="681991538434031708">"تم تجاوز الحد الأقصى لعدد محاولات فتح الجهاز بالتعرف على الوجه"</string> + <string name="faceunlock_multiple_failures" msgid="681991538434031708">"تم تجاوز الحد الأقصى لعدد محاولات فتح الجهاز ببصمة الوجه"</string> <string name="lockscreen_missing_sim_message_short" msgid="1229301273156907613">"لا تتوفر شريحة SIM."</string> <string name="lockscreen_missing_sim_message" product="tablet" msgid="3986843848305639161">"لا تتوفر شريحة SIM في الجهاز اللوحي."</string> <string name="lockscreen_missing_sim_message" product="tv" msgid="3903140876952198273">"لا تتوفر شريحة SIM في جهاز Android TV."</string> @@ -1077,7 +1077,7 @@ <string name="keyguard_accessibility_expand_lock_area" msgid="4215280881346033434">"توسيع منطقة فتح القفل."</string> <string name="keyguard_accessibility_slide_unlock" msgid="2968195219692413046">"فتح القفل باستخدام التمرير."</string> <string name="keyguard_accessibility_pattern_unlock" msgid="8669128146589233293">"فتح القفل باستخدام النقش."</string> - <string name="keyguard_accessibility_face_unlock" msgid="4533832120787386728">"فتح الجهاز بالتعرف على الوجه"</string> + <string name="keyguard_accessibility_face_unlock" msgid="4533832120787386728">"فتح الجهاز ببصمة الوجه"</string> <string name="keyguard_accessibility_pin_unlock" msgid="4020864007967340068">"فتح القفل باستخدام رمز PIN."</string> <string name="keyguard_accessibility_sim_pin_unlock" msgid="4895939120871890557">"فتح قفل رقم التعريف الشخصي لشريحة SIM."</string> <string name="keyguard_accessibility_sim_puk_unlock" msgid="3459003464041899101">"فتح قفل مفتاح PUK لشريحة SIM."</string> @@ -1526,8 +1526,8 @@ <string name="permission_request_notification_title" msgid="1810025922441048273">"الإذن مطلوب"</string> <string name="permission_request_notification_with_subtitle" msgid="3743417870360129298">"الإذن مطلوب\nللحساب <xliff:g id="ACCOUNT">%s</xliff:g>."</string> <string name="permission_request_notification_for_app_with_subtitle" msgid="1298704005732851350">"طلب تطبيق <xliff:g id="APP">%1$s</xliff:g> الإذن بالدخول\nإلى حساب <xliff:g id="ACCOUNT">%2$s</xliff:g>."</string> - <string name="forward_intent_to_owner" msgid="4620359037192871015">"أنت تستخدم هذا التطبيق خارج ملفك الشخصي للعمل"</string> - <string name="forward_intent_to_work" msgid="3620262405636021151">"أنت تستخدم هذا التطبيق في ملفك الشخصي للعمل"</string> + <string name="forward_intent_to_owner" msgid="4620359037192871015">"أنت تستخدم هذا التطبيق خارج ملف العمل الخاص بك"</string> + <string name="forward_intent_to_work" msgid="3620262405636021151">"أنت تستخدم هذا التطبيق في ملف العمل الخاص بك"</string> <string name="input_method_binding_label" msgid="1166731601721983656">"طريقة الإرسال"</string> <string name="sync_binding_label" msgid="469249309424662147">"مزامنة"</string> <string name="accessibility_binding_label" msgid="1974602776545801715">"سهولة الاستخدام"</string> @@ -1656,7 +1656,7 @@ <string name="SetupCallDefault" msgid="5581740063237175247">"هل تريد قبول المكالمة؟"</string> <string name="activity_resolver_use_always" msgid="5575222334666843269">"دائمًا"</string> <string name="activity_resolver_use_once" msgid="948462794469672658">"مرة واحدة فقط"</string> - <string name="activity_resolver_work_profiles_support" msgid="4071345609235361269">"لا يدعم %1$s الملفات الشخصية للعمل"</string> + <string name="activity_resolver_work_profiles_support" msgid="4071345609235361269">"لا يدعم %1$s ملفات العمل"</string> <string name="default_audio_route_name" product="tablet" msgid="367936735632195517">"الجهاز اللوحي"</string> <string name="default_audio_route_name" product="tv" msgid="4908971385068087367">"التلفزيون"</string> <string name="default_audio_route_name" product="default" msgid="9213546147739983977">"الهاتف"</string> @@ -2228,7 +2228,7 @@ <string name="resolver_switch_on_work" msgid="4527096360772311894">"إلغاء الإيقاف المؤقت"</string> <string name="resolver_no_work_apps_available" msgid="3298291360133337270">"ما مِن تطبيقات عمل."</string> <string name="resolver_no_personal_apps_available" msgid="6284837227019594881">"ما مِن تطبيقات شخصية."</string> - <string name="miniresolver_open_work" msgid="6286176185835401931">"هل تريد فتح تطبيق \"<xliff:g id="APP">%s</xliff:g>\" في ملفك الشخصي للعمل؟"</string> + <string name="miniresolver_open_work" msgid="6286176185835401931">"هل تريد فتح تطبيق \"<xliff:g id="APP">%s</xliff:g>\" في ملف العمل الخاص بك؟"</string> <string name="miniresolver_open_in_personal" msgid="807427577794490375">"هل تريد فتح المحتوى في تطبيق \"<xliff:g id="APP">%s</xliff:g>\" في الملف الشخصي؟"</string> <string name="miniresolver_open_in_work" msgid="941341494673509916">"هل تريد فتح المحتوى في تطبيق \"<xliff:g id="APP">%s</xliff:g>\" في ملف العمل؟"</string> <string name="miniresolver_call_in_work" msgid="528779988307529039">"هل تريد الاتصال من تطبيق العمل؟"</string> @@ -2434,8 +2434,8 @@ <string name="fingerprint_dangling_notification_msg_2" msgid="7925203589860744456">"لا يمكن بعد الآن التعرّف على \"<xliff:g id="FINGERPRINT_0">%1$s</xliff:g>\" و\"<xliff:g id="FINGERPRINT_1">%2$s</xliff:g>\"."</string> <string name="fingerprint_dangling_notification_msg_all_deleted_1" msgid="1824812666549916586">"لا يمكن بعد الآن التعرّف على \"<xliff:g id="FINGERPRINT">%s</xliff:g>\". يجب ضبط ميزة \"فتح الجهاز ببصمة الإصبع\" مجددًا."</string> <string name="fingerprint_dangling_notification_msg_all_deleted_2" msgid="5974657382960155099">"لا يمكن بعد الآن التعرّف على \"<xliff:g id="FINGERPRINT_0">%1$s</xliff:g>\" و\"<xliff:g id="FINGERPRINT_1">%2$s</xliff:g>\". يجب ضبط ميزة \"فتح الجهاز ببصمة الإصبع\" مجددًا."</string> - <string name="face_dangling_notification_title" msgid="947852541060975473">"إعادة إعداد ميزة \"فتح الجهاز بالتعرّف على الوجه\""</string> - <string name="face_dangling_notification_msg" msgid="746235263598985384">"لا يمكن بعد الآن التعرّف على نموذج الوجه الخاص بك. يجب ضبط ميزة \"فتح الجهاز بالتعرّف على الوجه\" مجددًا."</string> + <string name="face_dangling_notification_title" msgid="947852541060975473">"إعادة إعداد ميزة \"فتح الجهاز ببصمة الوجه\""</string> + <string name="face_dangling_notification_msg" msgid="746235263598985384">"لا يمكن بعد الآن التعرّف على نموذج الوجه الخاص بك. يجب ضبط ميزة \"فتح الجهاز ببصمة الوجه\" مجددًا."</string> <string name="biometric_dangling_notification_action_set_up" msgid="8246885009807817961">"إعداد"</string> <string name="biometric_dangling_notification_action_not_now" msgid="8095249216864443491">"لاحقًا"</string> <string name="bg_user_sound_notification_title_alarm" msgid="5251678483393143527">"تنبيه لـ \"<xliff:g id="USER_NAME">%s</xliff:g>\""</string> diff --git a/core/res/res/values-az/strings.xml b/core/res/res/values-az/strings.xml index 93976f9d6cdf..86c4c359b35c 100644 --- a/core/res/res/values-az/strings.xml +++ b/core/res/res/values-az/strings.xml @@ -2434,7 +2434,7 @@ <string name="face_dangling_notification_msg" msgid="746235263598985384">"Üz modeliniz artıq tanınmır. Üzlə Kilidaçmanı yenidən ayarlayın."</string> <string name="biometric_dangling_notification_action_set_up" msgid="8246885009807817961">"Ayarlayın"</string> <string name="biometric_dangling_notification_action_not_now" msgid="8095249216864443491">"İndi yox"</string> - <string name="bg_user_sound_notification_title_alarm" msgid="5251678483393143527">"<xliff:g id="USER_NAME">%s</xliff:g> üçün alarm"</string> + <string name="bg_user_sound_notification_title_alarm" msgid="5251678483393143527">"<xliff:g id="USER_NAME">%s</xliff:g> üçün zəngli saat"</string> <string name="bg_user_sound_notification_button_switch_user" msgid="3091969648572788946">"İstifadəçini dəyişin"</string> <string name="bg_user_sound_notification_button_mute" msgid="4942158515665615243">"Susdurun"</string> <string name="bg_user_sound_notification_message" msgid="8613881975316976673">"Susdurmaq üçün toxunun"</string> diff --git a/core/res/res/values-bs/strings.xml b/core/res/res/values-bs/strings.xml index 78a74a893219..c950d7c8d093 100644 --- a/core/res/res/values-bs/strings.xml +++ b/core/res/res/values-bs/strings.xml @@ -1067,7 +1067,7 @@ <string name="keyguard_accessibility_user_selector" msgid="1466067610235696600">"Biranje korisnika"</string> <string name="keyguard_accessibility_status" msgid="6792745049712397237">"Status"</string> <string name="keyguard_accessibility_camera" msgid="7862557559464986528">"Kamera"</string> - <string name="keygaurd_accessibility_media_controls" msgid="2267379779900620614">"Upravljanje medijima"</string> + <string name="keygaurd_accessibility_media_controls" msgid="2267379779900620614">"Kontrole medija"</string> <string name="keyguard_accessibility_widget_reorder_start" msgid="7066213328912939191">"Promjena rasporeda widgeta je počela."</string> <string name="keyguard_accessibility_widget_reorder_end" msgid="1083806817600593490">"Promjena rasporeda widgeta je završena."</string> <string name="keyguard_accessibility_widget_deleted" msgid="1509738950119878705">"Widget <xliff:g id="WIDGET_INDEX">%1$s</xliff:g> je izbrisan."</string> diff --git a/core/res/res/values-en-rAU/strings.xml b/core/res/res/values-en-rAU/strings.xml index 646e87db97e6..a58b26211d39 100644 --- a/core/res/res/values-en-rAU/strings.xml +++ b/core/res/res/values-en-rAU/strings.xml @@ -2434,7 +2434,7 @@ <string name="face_dangling_notification_msg" msgid="746235263598985384">"Your face model can no longer be recognised. Set up Face Unlock again."</string> <string name="biometric_dangling_notification_action_set_up" msgid="8246885009807817961">"Set up"</string> <string name="biometric_dangling_notification_action_not_now" msgid="8095249216864443491">"Not now"</string> - <string name="bg_user_sound_notification_title_alarm" msgid="5251678483393143527">"Alarm for <xliff:g id="USER_NAME">%s</xliff:g>"</string> + <string name="bg_user_sound_notification_title_alarm" msgid="5251678483393143527">"Alarm for: <xliff:g id="USER_NAME">%s</xliff:g>"</string> <string name="bg_user_sound_notification_button_switch_user" msgid="3091969648572788946">"Switch user"</string> <string name="bg_user_sound_notification_button_mute" msgid="4942158515665615243">"Mute"</string> <string name="bg_user_sound_notification_message" msgid="8613881975316976673">"Tap to mute sound"</string> diff --git a/core/res/res/values-en-rGB/strings.xml b/core/res/res/values-en-rGB/strings.xml index 6f83d88daaa2..234eb7bcf1e1 100644 --- a/core/res/res/values-en-rGB/strings.xml +++ b/core/res/res/values-en-rGB/strings.xml @@ -2434,7 +2434,7 @@ <string name="face_dangling_notification_msg" msgid="746235263598985384">"Your face model can no longer be recognised. Set up Face Unlock again."</string> <string name="biometric_dangling_notification_action_set_up" msgid="8246885009807817961">"Set up"</string> <string name="biometric_dangling_notification_action_not_now" msgid="8095249216864443491">"Not now"</string> - <string name="bg_user_sound_notification_title_alarm" msgid="5251678483393143527">"Alarm for <xliff:g id="USER_NAME">%s</xliff:g>"</string> + <string name="bg_user_sound_notification_title_alarm" msgid="5251678483393143527">"Alarm for: <xliff:g id="USER_NAME">%s</xliff:g>"</string> <string name="bg_user_sound_notification_button_switch_user" msgid="3091969648572788946">"Switch user"</string> <string name="bg_user_sound_notification_button_mute" msgid="4942158515665615243">"Mute"</string> <string name="bg_user_sound_notification_message" msgid="8613881975316976673">"Tap to mute sound"</string> diff --git a/core/res/res/values-en-rIN/strings.xml b/core/res/res/values-en-rIN/strings.xml index 3f194faecdbc..8c2a92e18577 100644 --- a/core/res/res/values-en-rIN/strings.xml +++ b/core/res/res/values-en-rIN/strings.xml @@ -2434,7 +2434,7 @@ <string name="face_dangling_notification_msg" msgid="746235263598985384">"Your face model can no longer be recognised. Set up Face Unlock again."</string> <string name="biometric_dangling_notification_action_set_up" msgid="8246885009807817961">"Set up"</string> <string name="biometric_dangling_notification_action_not_now" msgid="8095249216864443491">"Not now"</string> - <string name="bg_user_sound_notification_title_alarm" msgid="5251678483393143527">"Alarm for <xliff:g id="USER_NAME">%s</xliff:g>"</string> + <string name="bg_user_sound_notification_title_alarm" msgid="5251678483393143527">"Alarm for: <xliff:g id="USER_NAME">%s</xliff:g>"</string> <string name="bg_user_sound_notification_button_switch_user" msgid="3091969648572788946">"Switch user"</string> <string name="bg_user_sound_notification_button_mute" msgid="4942158515665615243">"Mute"</string> <string name="bg_user_sound_notification_message" msgid="8613881975316976673">"Tap to mute sound"</string> diff --git a/core/res/res/values-fr-rCA/strings.xml b/core/res/res/values-fr-rCA/strings.xml index b4dbd4335afd..7f99750ab923 100644 --- a/core/res/res/values-fr-rCA/strings.xml +++ b/core/res/res/values-fr-rCA/strings.xml @@ -622,7 +622,7 @@ <string name="permlab_disableKeyguard" msgid="3605253559020928505">"désactiver le verrouillage de l\'écran"</string> <string name="permdesc_disableKeyguard" msgid="3223710003098573038">"Permet à l\'appli de désactiver le verrouillage des touches et toute mesure de sécurité par mot de passe associée. Par exemple, votre téléphone désactive le verrouillage des touches lorsque vous recevez un appel, puis le réactive lorsque vous raccrochez."</string> <string name="permlab_requestPasswordComplexity" msgid="1808977190557794109">"demander la complexité du verrouillage d\'écran"</string> - <string name="permdesc_requestPasswordComplexity" msgid="1130556896836258567">"Autorise l\'appli à apprendre le niveau de complexité de l\'écran de verrouillage (élevé, moyen, faible ou aucun), qui indique la gamme possible de longueur et de type de verrouillage d\'écran. L\'appli peut aussi suggérer aux utilisateurs de mettre à jour l\'écran de verrouillage afin d\'utiliser un certain niveau de complexité, mais ils peuvent ignorer la suggestion. Notez que le verrouillage d\'écran n\'est pas stocké en texte brut pour de manière à ce que l\'appli n\'ait pas accès au mot de passe exact."</string> + <string name="permdesc_requestPasswordComplexity" msgid="1130556896836258567">"Autorise l\'appli à apprendre le niveau de complexité du Verrouillage de l\'écran (élevé, moyen, faible ou aucun), ce qui indique les différentes possibilités de longueur et de type de verrouillage d\'écran. L\'appli peut aussi suggérer aux utilisateurs de mettre à jour le Verrouillage de l\'écran afin d\'atteindre un certain niveau de complexité, mais ces derniers peuvent ignorer la suggestion. Notez que le Verrouillage de l\'écran n\'est pas stocké en texte brut pour que l\'appli n\'ait pas accès au mot de passe exact."</string> <string name="permlab_postNotification" msgid="4875401198597803658">"afficher les notifications"</string> <string name="permdesc_postNotification" msgid="5974977162462877075">"Permet à l\'appli d\'afficher les notifications"</string> <string name="permlab_turnScreenOn" msgid="219344053664171492">"allumer l\'écran"</string> @@ -829,7 +829,7 @@ <string name="permdesc_startViewAppFeatures" msgid="7207240860165206107">"Permet au détenteur de commencer à afficher les renseignements sur les fonctionnalités d\'une appli."</string> <string name="permlab_highSamplingRateSensors" msgid="3941068435726317070">"accéder aux données des capteurs à un taux d’échantillonnage élevé"</string> <string name="permdesc_highSamplingRateSensors" msgid="8430061978931155995">"Permet à l’appli d’échantillonner les données des capteurs à une fréquence supérieure à 200 Hz"</string> - <string name="permlab_updatePackagesWithoutUserAction" msgid="3363272609642618551">"Mettre à jour l\'appli sans intervention de l\'utilisateur"</string> + <string name="permlab_updatePackagesWithoutUserAction" msgid="3363272609642618551">"mettre à jour l\'appli sans intervention de l\'utilisateur"</string> <string name="permdesc_updatePackagesWithoutUserAction" msgid="4567739631260526366">"Permet à une appli précédemment installée de se mettre à jour sans intervention de l\'utilisateur"</string> <string name="permlab_writeVerificationStateE2eeContactKeys" msgid="3990742344778360457">"mettre à jour les états des vérifications des clés de contact chiffrées de bout en bout qui appartiennent à d\'autres applis"</string> <string name="permdesc_writeVerificationStateE2eeContactKeys" msgid="8453156829747427041">"Autorise l\'appli à mettre à jour les états des vérifications des clés de contact chiffrées de bout en bout qui appartiennent à d\'autres applis"</string> @@ -1417,7 +1417,7 @@ <string name="console_running_notification_title" msgid="6087888939261635904">"La console série est activée"</string> <string name="console_running_notification_message" msgid="7892751888125174039">"La performance est réduite. Pour désactiver cette fonction, vérifier le programme d\'amorçage."</string> <string name="mte_override_notification_title" msgid="4731115381962792944">"Extension MTE expérimentale activée"</string> - <string name="mte_override_notification_message" msgid="2441170442725738942">"La performance et la stabilité pourraient être affectées. Redémarrez l\'appareil pour la désactiver. Si vous l\'activez au moyen de la propriété arm64.memtag.bootctl, définissez d\'abord celle-ci à « none »."</string> + <string name="mte_override_notification_message" msgid="2441170442725738942">"La performance et la stabilité pourraient être affectées. Redémarrez pour désactiver. Si vous l\'activez au moyen de la propriété arm64.memtag.bootctl, définissez d\'abord celle-ci à « none »."</string> <string name="usb_contaminant_detected_title" msgid="4359048603069159678">"Liquide ou débris dans le port USB"</string> <string name="usb_contaminant_detected_message" msgid="7346100585390795743">"Le port USB est désactivé automatiquement. Touchez ici pour en savoir plus."</string> <string name="usb_contaminant_not_detected_title" msgid="2651167729563264053">"Autorisation d\'utiliser le port USB"</string> @@ -1480,10 +1480,10 @@ <string name="ext_media_move_success_message" msgid="9159542002276982979">"Contenu déplacé vers <xliff:g id="NAME">%s</xliff:g>"</string> <string name="ext_media_move_failure_title" msgid="3184577479181333665">"Impossible de déplacer le contenu"</string> <string name="ext_media_move_failure_message" msgid="4197306718121869335">"Essayez de déplacer le contenu de nouveau"</string> - <string name="ext_media_status_removed" msgid="241223931135751691">"Supprimée"</string> + <string name="ext_media_status_removed" msgid="241223931135751691">"Supprimé"</string> <string name="ext_media_status_unmounted" msgid="8145812017295835941">"Éjectée"</string> <string name="ext_media_status_checking" msgid="159013362442090347">"Vérification en cours…"</string> - <string name="ext_media_status_mounted" msgid="3459448555811203459">"Prête"</string> + <string name="ext_media_status_mounted" msgid="3459448555811203459">"Prêt"</string> <string name="ext_media_status_mounted_ro" msgid="1974809199760086956">"En lecture seule"</string> <string name="ext_media_status_bad_removal" msgid="508448566481406245">"Retrait risqué"</string> <string name="ext_media_status_unmountable" msgid="7043574843541087748">"Corrompue"</string> @@ -1537,7 +1537,7 @@ <string name="vpn_title" msgid="5906991595291514182">"RPV activé"</string> <string name="vpn_title_long" msgid="6834144390504619998">"RPV activé par <xliff:g id="APP">%s</xliff:g>"</string> <string name="vpn_text" msgid="2275388920267251078">"Appuyez ici pour gérer le réseau."</string> - <string name="vpn_text_long" msgid="278540576806169831">"Connecté à <xliff:g id="SESSION">%s</xliff:g>. Appuyez ici pour gérer le réseau."</string> + <string name="vpn_text_long" msgid="278540576806169831">"Connecté à <xliff:g id="SESSION">%s</xliff:g>. Touchez ici pour gérer le réseau."</string> <string name="vpn_lockdown_connecting" msgid="6096725311950342607">"RPV permanent en cours de connexion…"</string> <string name="vpn_lockdown_connected" msgid="2853127976590658469">"RPV permanent connecté"</string> <string name="vpn_lockdown_disconnected" msgid="5573611651300764955">"Déconnecté du RPV permanent"</string> @@ -2151,7 +2151,7 @@ <string name="nas_upgrade_notification_enable_action" msgid="3046406808378726874">"OK"</string> <string name="nas_upgrade_notification_disable_action" msgid="3794833210043497982">"Désactiver"</string> <string name="nas_upgrade_notification_learn_more_action" msgid="7011130656195423947">"En savoir plus"</string> - <string name="nas_upgrade_notification_learn_more_content" msgid="3735480566983530650">"Les notifications améliorées ont remplacé les notifications adaptatives Android sous Android 12. Cette fonctionnalité vous présente des suggestions d\'actions et de réponses, et organise vos notifications.\n\nLes notifications améliorées peuvent accéder au contenu de toutes les notifications, y compris les renseignements personnels comme le nom des contacts et les messages. Cette fonctionnalité peut aussi fermer des notifications ou interagir avec elles, comme répondre aux appels téléphoniques et gérer le mode Ne pas déranger."</string> + <string name="nas_upgrade_notification_learn_more_content" msgid="3735480566983530650">"Les notifications améliorées ont remplacé les notifications adaptatives Android sous Android 12. Cette fonctionnalité vous présente des suggestions d\'actions et de réponse, et organise vos notifications.\n\nLes notifications améliorées peuvent accéder au contenu de toutes les notifications, y compris les renseignements personnels comme le nom des contacts et les messages. Cette fonctionnalité peut aussi fermer des notifications ou interagir avec elles, comme répondre aux appels téléphoniques et gérer le mode Ne pas déranger."</string> <string name="dynamic_mode_notification_channel_name" msgid="2986926422100223328">"Notification d\'information du mode Routine"</string> <string name="dynamic_mode_notification_title" msgid="1388718452788985481">"Économiseur de pile activé"</string> <string name="dynamic_mode_notification_summary" msgid="1639031262484979689">"Réduction de l\'utilisation de la pile pour en prolonger l\'autonomie"</string> diff --git a/core/res/res/values-is/strings.xml b/core/res/res/values-is/strings.xml index a81566c7ea15..b2e03f395eb6 100644 --- a/core/res/res/values-is/strings.xml +++ b/core/res/res/values-is/strings.xml @@ -2434,7 +2434,7 @@ <string name="face_dangling_notification_msg" msgid="746235263598985384">"Ekki er hægt að bera kennsl á andlitslíkanið þitt lengur. Settu upp andlitskenni aftur."</string> <string name="biometric_dangling_notification_action_set_up" msgid="8246885009807817961">"Setja upp"</string> <string name="biometric_dangling_notification_action_not_now" msgid="8095249216864443491">"Ekki núna"</string> - <string name="bg_user_sound_notification_title_alarm" msgid="5251678483393143527">"Viðvörun fyrir <xliff:g id="USER_NAME">%s</xliff:g>"</string> + <string name="bg_user_sound_notification_title_alarm" msgid="5251678483393143527">"Viðvörun fyrir: <xliff:g id="USER_NAME">%s</xliff:g>"</string> <string name="bg_user_sound_notification_button_switch_user" msgid="3091969648572788946">"Skipta um notanda"</string> <string name="bg_user_sound_notification_button_mute" msgid="4942158515665615243">"Þagga"</string> <string name="bg_user_sound_notification_message" msgid="8613881975316976673">"Ýttu til að þagga hljóð"</string> diff --git a/core/res/res/values-it-feminine/strings.xml b/core/res/res/values-it-feminine/strings.xml index 407417d3292d..141b46768311 100644 --- a/core/res/res/values-it-feminine/strings.xml +++ b/core/res/res/values-it-feminine/strings.xml @@ -20,7 +20,6 @@ <resources xmlns:android="http://schemas.android.com/apk/res/android" xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> - <string name="relationTypeChild" msgid="9076258911292693601">"Figlia"</string> <string name="relationTypeFriend" msgid="3192092625893980574">"Amica"</string> <string name="relationTypeSpouse" msgid="6916682664436031703">"Moglie"</string> </resources> diff --git a/core/res/res/values-it-masculine/strings.xml b/core/res/res/values-it-masculine/strings.xml index 823006bbe72d..7310eb868f41 100644 --- a/core/res/res/values-it-masculine/strings.xml +++ b/core/res/res/values-it-masculine/strings.xml @@ -20,7 +20,6 @@ <resources xmlns:android="http://schemas.android.com/apk/res/android" xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> - <string name="relationTypeChild" msgid="9076258911292693601">"Figlio"</string> <string name="relationTypeFriend" msgid="3192092625893980574">"Amico"</string> <string name="relationTypeSpouse" msgid="6916682664436031703">"Marito"</string> </resources> diff --git a/core/res/res/values-it-neuter/strings.xml b/core/res/res/values-it-neuter/strings.xml index d5ec313ea1b3..ce433d728d23 100644 --- a/core/res/res/values-it-neuter/strings.xml +++ b/core/res/res/values-it-neuter/strings.xml @@ -20,7 +20,6 @@ <resources xmlns:android="http://schemas.android.com/apk/res/android" xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> - <string name="relationTypeChild" msgid="9076258911292693601">"Figliə"</string> <string name="relationTypeFriend" msgid="3192092625893980574">"Amicə"</string> <string name="relationTypeSpouse" msgid="6916682664436031703">"Coniuge"</string> </resources> diff --git a/core/res/res/values-iw/strings.xml b/core/res/res/values-iw/strings.xml index 355a0e9185a8..76e4e83c6fad 100644 --- a/core/res/res/values-iw/strings.xml +++ b/core/res/res/values-iw/strings.xml @@ -1275,7 +1275,7 @@ <string name="unsupported_display_size_show" msgid="980129850974919375">"להציג תמיד"</string> <string name="unsupported_compile_sdk_message" msgid="7326293500707890537">"<xliff:g id="APP_NAME">%1$s</xliff:g> נבנתה לגרסה לא תואמת של מערכת ההפעלה של Android ועלולה להתנהג באופן לא צפוי. ייתכן שקיימת גרסה מעודכנת של האפליקציה."</string> <string name="unsupported_compile_sdk_show" msgid="1601210057960312248">"להציג תמיד"</string> - <string name="unsupported_compile_sdk_check_update" msgid="1103639989147664456">"האם יש עדכון חדש?"</string> + <string name="unsupported_compile_sdk_check_update" msgid="1103639989147664456">"יש עדכון חדש?"</string> <string name="smv_application" msgid="3775183542777792638">"האפליקציה <xliff:g id="APPLICATION">%1$s</xliff:g> (תהליך <xliff:g id="PROCESS">%2$s</xliff:g>) הפרה את מדיניות StrictMode באכיפה עצמית שלה."</string> <string name="smv_process" msgid="1398801497130695446">"התהליך <xliff:g id="PROCESS">%1$s</xliff:g> הפר את מדיניות StrictMode באכיפה עצמית."</string> <string name="android_upgrading_title" product="default" msgid="7279077384220829683">"הטלפון מתעדכן…"</string> diff --git a/core/res/res/values-sq/strings.xml b/core/res/res/values-sq/strings.xml index 5124c27311ec..998c960f3b56 100644 --- a/core/res/res/values-sq/strings.xml +++ b/core/res/res/values-sq/strings.xml @@ -1428,8 +1428,7 @@ <string name="share_remote_bugreport_action" msgid="7630880678785123682">"SHPËRNDAJ"</string> <string name="decline_remote_bugreport_action" msgid="4040894777519784346">"REFUZO"</string> <string name="select_input_method" msgid="3971267998568587025">"Zgjidh metodën e hyrjes"</string> - <!-- no translation found for input_method_language_settings (8069089418056819437) --> - <skip /> + <string name="input_method_language_settings" msgid="8069089418056819437">"Cilësimet e gjuhës"</string> <string name="show_ime" msgid="6406112007347443383">"Mbaje në ekran ndërsa tastiera fizike është aktive"</string> <string name="hardware" msgid="3611039921284836033">"Përdor tastierën në ekran"</string> <string name="select_keyboard_layout_notification_title" msgid="5823199895322205589">"Konfiguro <xliff:g id="DEVICE_NAME">%s</xliff:g>"</string> diff --git a/core/res/res/values/attrs.xml b/core/res/res/values/attrs.xml index 7cc9e13db5cf..440219de9561 100644 --- a/core/res/res/values/attrs.xml +++ b/core/res/res/values/attrs.xml @@ -1078,6 +1078,11 @@ <!-- Background color to use for tooltip popups. --> <attr name="tooltipBackgroundColor" format="reference|color" /> + <attr name="tooltipCornerRadius" format="dimension" /> + <attr name="tooltipHorizontalPadding" format="dimension" /> + <attr name="tooltipVerticalPadding" format="dimension" /> + <attr name="tooltipFontSize" format="dimension" /> + <!-- Theme to use for Search Dialogs. --> <attr name="searchDialogTheme" format="reference" /> diff --git a/core/res/res/values/attrs_manifest.xml b/core/res/res/values/attrs_manifest.xml index 2e3dbda5e41c..0be33c2e7a03 100644 --- a/core/res/res/values/attrs_manifest.xml +++ b/core/res/res/values/attrs_manifest.xml @@ -3296,8 +3296,8 @@ usually TVs. <p>Requires permission {@code android.permission.DISABLE_SYSTEM_SOUND_EFFECTS}. --> <attr name="playHomeTransitionSound" format="boolean"/> - <!-- Indicates whether the activity can be displayed on a remote device which may or - may not be running Android. --> + <!-- Indicates whether the activity can be displayed on a display that may belong to a + remote device which may or may not be running Android. --> <attr name="canDisplayOnRemoteDevices" format="boolean"/> <attr name="allowUntrustedActivityEmbedding" /> <attr name="knownActivityEmbeddingCerts" /> diff --git a/core/res/res/values/config.xml b/core/res/res/values/config.xml index 2afc30315bd1..495af5b35f5f 100644 --- a/core/res/res/values/config.xml +++ b/core/res/res/values/config.xml @@ -1399,6 +1399,10 @@ Settings.System.RING_VIBRATION_INTENSITY more details on the constant values and meanings. --> <integer name="config_defaultRingVibrationIntensity">2</integer> + <!-- The default intensity level for keyboard vibrations. Note that this will only be applied + on devices where config_keyboardVibrationSettingsSupported is true, otherwise the + keyboard vibration will follow config_defaultHapticFeedbackIntensity --> + <integer name="config_defaultKeyboardVibrationIntensity">2</integer> <!-- Whether to use the strict phone number matcher by default. --> <bool name="config_use_strict_phone_number_comparation">false</bool> @@ -6154,10 +6158,6 @@ is enabled and activity is connected to the camera in fullscreen. --> <bool name="config_isWindowManagerCameraCompatSplitScreenAspectRatioEnabled">false</bool> - <!-- Whether a camera compat controller is enabled to allow the user to apply or revert - treatment for stretched issues in camera viewfinder. --> - <bool name="config_isCameraCompatControlForStretchedIssuesEnabled">false</bool> - <!-- Docking is a uiMode configuration change and will cause activities to relaunch if it's not handled. If true, the configuration change will be sent but activities will not be relaunched upon docking. Apps with desk resources will behave like normal, since they may diff --git a/core/res/res/values/dimens.xml b/core/res/res/values/dimens.xml index 6cba84be58c3..77b5587e77be 100644 --- a/core/res/res/values/dimens.xml +++ b/core/res/res/values/dimens.xml @@ -771,6 +771,7 @@ <dimen name="tooltip_precise_anchor_threshold">96dp</dimen> <!-- Extra tooltip offset used when anchoring to the mouse/touch position --> <dimen name="tooltip_precise_anchor_extra_offset">8dp</dimen> + <dimen name="tooltip_font_size">14sp</dimen> <!-- The max amount of scroll ItemTouchHelper will trigger if dragged view is out of RecyclerView's bounds.--> diff --git a/core/res/res/values/dimens_material.xml b/core/res/res/values/dimens_material.xml index 972fe7ed91de..35f35fb86a59 100644 --- a/core/res/res/values/dimens_material.xml +++ b/core/res/res/values/dimens_material.xml @@ -204,4 +204,9 @@ <dimen name="progress_bar_size_small">16dip</dimen> <dimen name="progress_bar_size_medium">48dp</dimen> <dimen name="progress_bar_size_large">76dp</dimen> + + <dimen name="tooltip_corner_radius_material">4dp</dimen> + <dimen name="tooltip_horizontal_padding_material">8dp</dimen> + <dimen name="tooltip_vertical_padding_material">4dp</dimen> + <dimen name="tooltip_font_size_material">12sp</dimen> </resources> diff --git a/core/res/res/values/strings.xml b/core/res/res/values/strings.xml index ec865f6c376f..e94db2dc7fc4 100644 --- a/core/res/res/values/strings.xml +++ b/core/res/res/values/strings.xml @@ -6555,4 +6555,7 @@ ul.</string> <string name="keyboard_shortcut_group_applications_maps">Maps</string> <!-- User visible title for the keyboard shortcut group containing system-wide application launch shortcuts. [CHAR-LIMIT=70] --> <string name="keyboard_shortcut_group_applications">Applications</string> + + <!-- Fingerprint loe notification string --> + <string name="fingerprint_loe_notification_msg">Your fingerprints can no longer be recognized. Set up Fingerprint Unlock again.</string> </resources> diff --git a/core/res/res/values/styles.xml b/core/res/res/values/styles.xml index aabc8ca5aef6..c084b4c1e834 100644 --- a/core/res/res/values/styles.xml +++ b/core/res/res/values/styles.xml @@ -998,7 +998,7 @@ please see styles_device_defaults.xml. <style name="TextAppearance.Tooltip"> <item name="fontFamily">sans-serif</item> - <item name="textSize">14sp</item> + <item name="textSize">?android:attr/tooltipFontSize</item> </style> <style name="Widget.ActivityChooserView"> diff --git a/core/res/res/values/symbols.xml b/core/res/res/values/symbols.xml index bc8c778c0671..8734b44e95f6 100644 --- a/core/res/res/values/symbols.xml +++ b/core/res/res/values/symbols.xml @@ -4223,6 +4223,7 @@ <java-symbol type="integer" name="config_defaultMediaVibrationIntensity" /> <java-symbol type="integer" name="config_defaultNotificationVibrationIntensity" /> <java-symbol type="integer" name="config_defaultRingVibrationIntensity" /> + <java-symbol type="integer" name="config_defaultKeyboardVibrationIntensity" /> <java-symbol type="bool" name="config_maskMainBuiltInDisplayCutout" /> @@ -4766,7 +4767,6 @@ <java-symbol type="bool" name="config_isCompatFakeFocusEnabled" /> <java-symbol type="bool" name="config_isWindowManagerCameraCompatTreatmentEnabled" /> <java-symbol type="bool" name="config_isWindowManagerCameraCompatSplitScreenAspectRatioEnabled" /> - <java-symbol type="bool" name="config_isCameraCompatControlForStretchedIssuesEnabled" /> <java-symbol type="bool" name="config_skipActivityRelaunchWhenDocking" /> <java-symbol type="bool" name="config_hideDisplayCutoutWithDisplayArea" /> @@ -5583,4 +5583,7 @@ <java-symbol type="string" name="keyboard_shortcut_group_applications_music" /> <java-symbol type="string" name="keyboard_shortcut_group_applications_sms" /> <java-symbol type="string" name="keyboard_shortcut_group_applications" /> + + <!-- Fingerprint loe notification string --> + <java-symbol type="string" name="fingerprint_loe_notification_msg" /> </resources> diff --git a/core/res/res/values/themes.xml b/core/res/res/values/themes.xml index c3d304dc35e1..3b3bb8dfc405 100644 --- a/core/res/res/values/themes.xml +++ b/core/res/res/values/themes.xml @@ -461,6 +461,10 @@ please see themes_device_defaults.xml. <item name="tooltipFrameBackground">@drawable/tooltip_frame</item> <item name="tooltipForegroundColor">@color/bright_foreground_light</item> <item name="tooltipBackgroundColor">@color/tooltip_background_light</item> + <item name="tooltipCornerRadius">@dimen/tooltip_corner_radius</item> + <item name="tooltipHorizontalPadding">@dimen/tooltip_horizontal_padding</item> + <item name="tooltipVerticalPadding">@dimen/tooltip_vertical_padding</item> + <item name="tooltipFontSize">@dimen/tooltip_font_size</item> <!-- Autofill: max width/height of the dataset picker as a fraction of screen size --> <item name="autofillDatasetPickerMaxWidth">@dimen/autofill_dataset_picker_max_width</item> @@ -582,9 +586,10 @@ please see themes_device_defaults.xml. <item name="floatingToolbarOpenDrawable">@drawable/ic_menu_moreoverflow_material_light</item> <item name="floatingToolbarDividerColor">@color/floating_popup_divider_light</item> - <!-- Tooltip popup colors --> + <!-- Tooltip popup styles --> <item name="tooltipForegroundColor">@color/bright_foreground_dark</item> <item name="tooltipBackgroundColor">@color/tooltip_background_dark</item> + </style> <!-- Variant of {@link #Theme_Light} with no title bar --> diff --git a/core/res/res/values/themes_material.xml b/core/res/res/values/themes_material.xml index 8e2fb34ec8a4..9f11208c97ec 100644 --- a/core/res/res/values/themes_material.xml +++ b/core/res/res/values/themes_material.xml @@ -408,8 +408,12 @@ please see themes_device_defaults.xml. <item name="colorProgressBackgroundNormal">?attr/colorControlNormal</item> <!-- Tooltip popup properties --> - <item name="tooltipForegroundColor">@color/foreground_material_light</item> - <item name="tooltipBackgroundColor">@color/tooltip_background_light</item> + <item name="tooltipForegroundColor">@color/system_on_surface_light</item> + <item name="tooltipBackgroundColor">@color/system_surface_light</item> + <item name="tooltipCornerRadius">@dimen/tooltip_corner_radius_material</item> + <item name="tooltipHorizontalPadding">@dimen/tooltip_horizontal_padding_material</item> + <item name="tooltipVerticalPadding">@dimen/tooltip_vertical_padding_material</item> + <item name="tooltipFontSize">@dimen/tooltip_font_size_material</item> </style> <!-- Material theme (light version). --> @@ -785,8 +789,13 @@ please see themes_device_defaults.xml. <item name="colorProgressBackgroundNormal">?attr/colorControlNormal</item> <!-- Tooltip popup properties --> - <item name="tooltipForegroundColor">@color/foreground_material_dark</item> - <item name="tooltipBackgroundColor">@color/tooltip_background_dark</item> + <item name="tooltipForegroundColor">@color/system_on_surface_dark</item> + <item name="tooltipBackgroundColor">@color/system_surface_dark</item> + <item name="tooltipCornerRadius">@dimen/tooltip_corner_radius_material</item> + <item name="tooltipHorizontalPadding">@dimen/tooltip_horizontal_padding_material</item> + <item name="tooltipVerticalPadding">@dimen/tooltip_vertical_padding_material</item> + <item name="tooltipFontSize">@dimen/tooltip_font_size_material</item> + </style> <!-- Variant of the material (light) theme that has a solid (opaque) action bar diff --git a/core/tests/coretests/Android.bp b/core/tests/coretests/Android.bp index 41696dfa782e..5793bbe306f1 100644 --- a/core/tests/coretests/Android.bp +++ b/core/tests/coretests/Android.bp @@ -284,3 +284,510 @@ android_ravenwood_test { ], auto_gen_config: true, } + +FLAKY_OR_IGNORED = [ + "androidx.test.filters.FlakyTest", + "org.junit.Ignore", +] + +test_module_config { + name: "FrameworksCoreTests_Presubmit", + base: "FrameworksCoreTests", + test_suites: [ + "device-tests", + "device-platinum-tests", + ], + include_annotations: ["android.platform.test.annotations.Presubmit"], + exclude_annotations: FLAKY_OR_IGNORED, +} + +test_module_config { + name: "FrameworksCoreTests_inputmethod", + base: "FrameworksCoreTests", + test_suites: [ + "device-tests", + "device-platinum-tests", + ], + include_filters: [ + "com.android.internal.inputmethod", + "android.view.inputmethod", + ], + exclude_annotations: ["androidx.test.filters.FlakyTest"], +} + +test_module_config { + name: "FrameworksCoreTests_context", + base: "FrameworksCoreTests", + test_suites: [ + "device-tests", + "device-platinum-tests", + ], + include_filters: ["android.content.ContextTest"], + exclude_annotations: FLAKY_OR_IGNORED, +} + +test_module_config { + name: "FrameworksCoreTests_keyguard_manager", + base: "FrameworksCoreTests", + test_suites: [ + "device-tests", + "device-platinum-tests", + ], + include_filters: ["android.app.KeyguardManagerTest"], + exclude_annotations: FLAKY_OR_IGNORED, +} + +test_module_config { + name: "FrameworksCoreTests_property_invalidated_cache", + base: "FrameworksCoreTests", + test_suites: [ + "device-tests", + "device-platinum-tests", + ], + include_filters: ["android.app.PropertyInvalidatedCacheTests"], + exclude_annotations: FLAKY_OR_IGNORED, +} + +test_module_config { + name: "FrameworksCoreTests_android_content", + base: "FrameworksCoreTests", + test_suites: [ + "device-tests", + "device-platinum-tests", + ], + include_filters: [ + "android.content.ContextTest", + "android.content.ComponentCallbacksControllerTest", + "android.content.ContextWrapperTest", + ], + exclude_annotations: FLAKY_OR_IGNORED, +} + +test_module_config { + name: "FrameworksCoreTests_sqlite", + base: "FrameworksCoreTests", + test_suites: [ + "device-tests", + "device-platinum-tests", + ], + include_filters: ["android.database.sqlite.SQLiteRawStatementTest"], + exclude_annotations: FLAKY_OR_IGNORED, +} + +test_module_config { + name: "FrameworksCoreTests_android_net", + base: "FrameworksCoreTests", + test_suites: [ + "device-tests", + "device-platinum-tests", + ], + include_filters: ["android.net"], + include_annotations: ["android.platform.test.annotations.Presubmit"], + exclude_annotations: FLAKY_OR_IGNORED, +} + +test_module_config { + name: "FrameworksCoreTests_battery_stats", + base: "FrameworksCoreTests", + test_suites: [ + "device-tests", + "device-platinum-tests", + ], + include_filters: ["com.android.internal.os.BatteryStatsTests"], + exclude_annotations: ["com.android.internal.os.SkipPresubmit"], +} + +test_module_config { + name: "FrameworksCoreTests_environment", + base: "FrameworksCoreTests", + test_suites: [ + "device-tests", + "device-platinum-tests", + ], + include_filters: ["android.os.EnvironmentTest"], +} + +test_module_config { + name: "FrameworksCoreTests_util_data_charset", + base: "FrameworksCoreTests", + test_suites: [ + "device-tests", + "device-platinum-tests", + ], + include_filters: [ + "com.android.internal.util.FastDataTest", + "android.util.CharsetUtilsTest", + ], +} + +test_module_config { + name: "FrameworksCoreTests_xml", + base: "FrameworksCoreTests", + test_suites: [ + "device-tests", + "device-platinum-tests", + ], + include_filters: [ + "android.util.XmlTest", + "android.util.BinaryXmlTest", + ], +} + +test_module_config { + name: "FrameworksCoreTests_util_apk", + base: "FrameworksCoreTests", + test_suites: [ + "device-tests", + "device-platinum-tests", + ], + include_filters: ["android.util.apk.SourceStampVerifierTest"], +} + +test_module_config { + name: "FrameworksCoreTests_textclassifier", + base: "FrameworksCoreTests", + test_suites: [ + "device-tests", + "device-platinum-tests", + ], + include_filters: ["android.view.textclassifier"], + exclude_annotations: ["androidx.test.filters.FlakyTest"], +} + +test_module_config { + name: "FrameworksCoreTests_internal_app", + base: "FrameworksCoreTests", + test_suites: [ + "device-tests", + "device-platinum-tests", + ], + include_filters: ["com.android.internal.app."], + exclude_filters: [ + "com.android.internal.app.WindowDecorActionBarTest", + "com.android.internal.app.IntentForwarderActivityTest", + ], +} + +test_module_config { + name: "FrameworksCoreTests_internal_content", + base: "FrameworksCoreTests", + test_suites: [ + "device-tests", + "device-platinum-tests", + ], + include_filters: ["com.android.internal.content."], +} + +test_module_config { + name: "FrameworksCoreTests_internal_infra", + base: "FrameworksCoreTests", + test_suites: [ + "device-tests", + "device-platinum-tests", + ], + include_filters: ["com.android.internal.infra."], +} + +test_module_config { + name: "FrameworksCoreTests_internal_jank", + base: "FrameworksCoreTests", + test_suites: [ + "device-tests", + "device-platinum-tests", + ], + include_filters: ["com.android.internal.jank"], + exclude_annotations: FLAKY_OR_IGNORED, +} + +test_module_config { + name: "FrameworksCoreTests_internal_os_binder", + base: "FrameworksCoreTests", + test_suites: [ + "device-tests", + "device-platinum-tests", + ], + include_filters: ["com.android.internal.os.BinderDeathDispatcherTest"], + exclude_annotations: ["com.android.internal.os.SkipPresubmit"], +} + +test_module_config { + name: "FrameworksCoreTests_internal_os_kernel", + base: "FrameworksCoreTests", + test_suites: [ + "device-tests", + "device-platinum-tests", + ], + include_filters: [ + "com.android.internal.os.KernelCpuUidClusterTimeReaderTest", + "com.android.internal.os.KernelCpuUidBpfMapReaderTest", + "com.android.internal.os.KernelCpuUidActiveTimeReaderTest", + "com.android.internal.os.KernelCpuUidFreqTimeReaderTest", + "com.android.internal.os.KernelSingleUidTimeReaderTest", + ], +} + +test_module_config { + name: "FrameworksCoreTests_server_power", + base: "FrameworksCoreTests", + test_suites: [ + "device-tests", + "device-platinum-tests", + ], + include_filters: ["com.android.server.power.stats.BstatsCpuTimesValidationTest"], +} + +test_module_config { + name: "FrameworksCoreTests_internal_security", + base: "FrameworksCoreTests", + test_suites: [ + "device-tests", + "device-platinum-tests", + ], + include_filters: ["com.android.internal.security."], + include_annotations: ["android.platform.test.annotations.Presubmit"], +} + +test_module_config { + name: "FrameworksCoreTests_internal_util_latency_tracker", + base: "FrameworksCoreTests", + test_suites: [ + "device-tests", + "device-platinum-tests", + ], + include_filters: ["com.android.internal.util.LatencyTrackerTest"], + exclude_annotations: FLAKY_OR_IGNORED, +} + +test_module_config { + name: "FrameworksCoreTests_content_capture_options", + base: "FrameworksCoreTests", + test_suites: [ + "device-tests", + "device-platinum-tests", + ], + include_filters: ["android.content.ContentCaptureOptionsTest"], + exclude_annotations: FLAKY_OR_IGNORED, +} + +test_module_config { + name: "FrameworksCoreTests_android_content_integrity", + base: "FrameworksCoreTests", + test_suites: [ + "device-tests", + "device-platinum-tests", + ], + include_filters: ["android.content.integrity."], +} + +test_module_config { + name: "FrameworksCoreTests_android_content_pm_PreSubmit", + base: "FrameworksCoreTests", + test_suites: [ + "device-tests", + "device-platinum-tests", + ], + include_filters: ["android.content.pm."], + include_annotations: ["android.platform.test.annotations.Presubmit"], + exclude_annotations: FLAKY_OR_IGNORED, +} + +test_module_config { + name: "FrameworksCoreTests_android_content_pm_PostSubmit", + base: "FrameworksCoreTests", + test_suites: [ + "device-tests", + "device-platinum-tests", + ], + include_filters: ["android.content.pm."], + include_annotations: ["android.platform.test.annotations.Postsubmit"], + exclude_annotations: FLAKY_OR_IGNORED, +} + +test_module_config { + name: "FrameworksCoreTests_android_content_res", + base: "FrameworksCoreTests", + test_suites: [ + "device-tests", + "device-platinum-tests", + ], + include_filters: ["android.content.res."], + include_annotations: ["android.platform.test.annotations.Presubmit"], + exclude_annotations: [ + "androidx.test.filters.FlakyTest", + "android.platform.test.annotations.Postsubmit", + "org.junit.Ignore", + ], +} + +test_module_config { + name: "FrameworksCoreTests_android_content_res_PostSubmit", + base: "FrameworksCoreTests", + test_suites: [ + "device-tests", + "device-platinum-tests", + ], + include_filters: ["android.content.res."], + include_annotations: ["android.platform.test.annotations.Postsubmit"], + exclude_annotations: FLAKY_OR_IGNORED, +} + +test_module_config { + name: "FrameworksCoreTests_android_service", + base: "FrameworksCoreTests", + test_suites: [ + "device-tests", + "device-platinum-tests", + ], + include_filters: [ + "android.service.euicc", + "android.service.notification", + "android.service.quicksettings", + "android.service.settings.suggestions", + "android.service.controls.templates", + "android.service.controls.actions", + "android.service.controls", + ], + exclude_annotations: ["org.junit.Ignore"], +} + +test_module_config { + name: "FrameworksCoreTests_android_view_contentcapture", + base: "FrameworksCoreTests", + test_suites: [ + "device-tests", + "device-platinum-tests", + ], + include_filters: ["android.view.contentcapture"], + exclude_annotations: FLAKY_OR_IGNORED, +} + +test_module_config { + name: "FrameworksCoreTests_android_view_contentprotection", + base: "FrameworksCoreTests", + test_suites: [ + "device-tests", + "device-platinum-tests", + ], + include_filters: ["android.view.contentprotection"], + exclude_annotations: FLAKY_OR_IGNORED, +} + +test_module_config { + name: "FrameworksCoreTests_com_android_internal_content_Presubmit", + base: "FrameworksCoreTests", + test_suites: [ + "device-tests", + "device-platinum-tests", + ], + include_filters: ["com.android.internal.content."], + include_annotations: ["android.platform.test.annotations.Presubmit"], + exclude_annotations: FLAKY_OR_IGNORED, +} + +test_module_config { + name: "FrameworksCoreTests_drawable", + base: "FrameworksCoreTests", + test_suites: [ + "device-tests", + "device-platinum-tests", + ], + include_filters: ["android.graphics.drawable.IconTest"], +} + +test_module_config { + name: "FrameworksCoreTests_accessibility_NO_FLAKES", + base: "FrameworksCoreTests", + test_suites: [ + "device-tests", + "device-platinum-tests", + ], + include_filters: [ + "com.android.internal.accessibility", + "android.accessibilityservice", + "android.view.accessibility", + ], + exclude_annotations: ["androidx.test.filters.FlakyTest"], +} + +test_module_config { + name: "FrameworksCoreTests_accessibility", + base: "FrameworksCoreTests", + test_suites: [ + "device-tests", + "device-platinum-tests", + ], + include_filters: [ + "com.android.internal.accessibility", + "android.accessibilityservice", + "android.view.accessibility", + ], +} + +test_module_config { + name: "FrameworksCoreTests_usage", + base: "FrameworksCoreTests", + test_suites: [ + "device-tests", + "device-platinum-tests", + ], + include_filters: ["android.app.usage"], +} + +test_module_config { + name: "FrameworksCoreTests_fastdata", + base: "FrameworksCoreTests", + test_suites: [ + "device-tests", + "device-platinum-tests", + ], + include_filters: ["com.android.internal.util.FastDataTest"], +} + +test_module_config { + name: "FrameworksCoreTests_hardware_input", + base: "FrameworksCoreTests", + test_suites: [ + "device-tests", + "device-platinum-tests", + ], + include_filters: ["android.hardware.input"], +} + +test_module_config { + name: "FrameworksCoreTests_view_verified", + base: "FrameworksCoreTests", + test_suites: [ + "device-tests", + "device-platinum-tests", + ], + include_filters: [ + "android.view.VerifiedMotionEventTest", + "android.view.VerifiedKeyEventTest", + ], +} + +test_module_config { + name: "FrameworksCoreTests_jank", + base: "FrameworksCoreTests", + test_suites: [ + "device-tests", + "device-platinum-tests", + ], + include_filters: [ + "com.android.internal.jank.FrameTrackerTest", + "com.android.internal.jank.InteractionJankMonitorTest", + "com.android.internal.util.LatencyTrackerTest", + ], + exclude_annotations: FLAKY_OR_IGNORED, +} + +test_module_config { + name: "FrameworksCoreTests_Platinum", + base: "FrameworksCoreTests", + test_suites: [ + "device-tests", + "device-platinum-tests", + ], + include_annotations: ["android.platform.test.annotations.PlatinumTest"], + exclude_annotations: FLAKY_OR_IGNORED, +} diff --git a/core/tests/coretests/src/android/accessibilityservice/AccessibilityShortcutInfoTest.java b/core/tests/coretests/src/android/accessibilityservice/AccessibilityShortcutInfoTest.java index eebc5789e935..ef7df59e01ef 100644 --- a/core/tests/coretests/src/android/accessibilityservice/AccessibilityShortcutInfoTest.java +++ b/core/tests/coretests/src/android/accessibilityservice/AccessibilityShortcutInfoTest.java @@ -29,9 +29,9 @@ import android.content.pm.PackageManager; import android.view.accessibility.AccessibilityManager; import android.view.accessibility.AccessibilityTestActivity; +import androidx.test.ext.junit.runners.AndroidJUnit4; import androidx.test.filters.SmallTest; import androidx.test.platform.app.InstrumentationRegistry; -import androidx.test.runner.AndroidJUnit4; import com.android.frameworks.coretests.R; diff --git a/core/tests/coretests/src/android/animation/ValueAnimatorTests.java b/core/tests/coretests/src/android/animation/ValueAnimatorTests.java index a102b3ed9971..eb463fd9a76b 100644 --- a/core/tests/coretests/src/android/animation/ValueAnimatorTests.java +++ b/core/tests/coretests/src/android/animation/ValueAnimatorTests.java @@ -30,9 +30,9 @@ import android.os.SystemClock; import android.view.Choreographer; import android.view.animation.LinearInterpolator; +import androidx.test.ext.junit.runners.AndroidJUnit4; import androidx.test.filters.MediumTest; import androidx.test.rule.ActivityTestRule; -import androidx.test.runner.AndroidJUnit4; import org.junit.After; import org.junit.Before; diff --git a/core/tests/coretests/src/android/app/ActivityManagerTest.java b/core/tests/coretests/src/android/app/ActivityManagerTest.java index 3c042bac895d..d850f86070bc 100644 --- a/core/tests/coretests/src/android/app/ActivityManagerTest.java +++ b/core/tests/coretests/src/android/app/ActivityManagerTest.java @@ -26,7 +26,7 @@ import static org.junit.Assert.assertTrue; import android.os.UserHandle; import android.platform.test.ravenwood.RavenwoodRule; -import androidx.test.runner.AndroidJUnit4; +import androidx.test.ext.junit.runners.AndroidJUnit4; import org.junit.Rule; import org.junit.Test; diff --git a/core/tests/coretests/src/android/app/ApplicationErrorReportTest.java b/core/tests/coretests/src/android/app/ApplicationErrorReportTest.java index 8dc5ad66194b..c4240a2d4260 100644 --- a/core/tests/coretests/src/android/app/ApplicationErrorReportTest.java +++ b/core/tests/coretests/src/android/app/ApplicationErrorReportTest.java @@ -21,8 +21,8 @@ import static org.junit.Assert.assertTrue; import android.app.ApplicationErrorReport.CrashInfo; +import androidx.test.ext.junit.runners.AndroidJUnit4; import androidx.test.filters.SmallTest; -import androidx.test.runner.AndroidJUnit4; import org.junit.Test; import org.junit.runner.RunWith; diff --git a/core/tests/coretests/src/android/app/ApplicationLoadersTest.java b/core/tests/coretests/src/android/app/ApplicationLoadersTest.java index 565e21d034a7..dfb8a23746c6 100644 --- a/core/tests/coretests/src/android/app/ApplicationLoadersTest.java +++ b/core/tests/coretests/src/android/app/ApplicationLoadersTest.java @@ -22,8 +22,8 @@ import static org.junit.Assert.assertNull; import android.content.pm.SharedLibraryInfo; +import androidx.test.ext.junit.runners.AndroidJUnit4; import androidx.test.filters.SmallTest; -import androidx.test.runner.AndroidJUnit4; import com.google.android.collect.Lists; diff --git a/core/tests/coretests/src/android/app/BackgroundStartPrivilegesTest.java b/core/tests/coretests/src/android/app/BackgroundStartPrivilegesTest.java index 982ad63d7e8d..cf6266c756ce 100644 --- a/core/tests/coretests/src/android/app/BackgroundStartPrivilegesTest.java +++ b/core/tests/coretests/src/android/app/BackgroundStartPrivilegesTest.java @@ -26,8 +26,8 @@ import static com.google.common.truth.Truth.assertThat; import android.os.Binder; import android.os.IBinder; +import androidx.test.ext.junit.runners.AndroidJUnit4; import androidx.test.filters.SmallTest; -import androidx.test.runner.AndroidJUnit4; import org.junit.Test; import org.junit.runner.RunWith; diff --git a/core/tests/coretests/src/android/app/LoaderLifecycleTest.java b/core/tests/coretests/src/android/app/LoaderLifecycleTest.java index e343383df3f1..2eb0bbed0182 100644 --- a/core/tests/coretests/src/android/app/LoaderLifecycleTest.java +++ b/core/tests/coretests/src/android/app/LoaderLifecycleTest.java @@ -28,9 +28,9 @@ import android.os.Handler; import android.os.Parcelable; import android.util.ArrayMap; +import androidx.test.ext.junit.runners.AndroidJUnit4; import androidx.test.filters.MediumTest; import androidx.test.rule.ActivityTestRule; -import androidx.test.runner.AndroidJUnit4; import org.junit.Rule; import org.junit.Test; diff --git a/core/tests/coretests/src/android/app/NotificationChannelGroupTest.java b/core/tests/coretests/src/android/app/NotificationChannelGroupTest.java index 046f5ac10e36..322893ceea2e 100644 --- a/core/tests/coretests/src/android/app/NotificationChannelGroupTest.java +++ b/core/tests/coretests/src/android/app/NotificationChannelGroupTest.java @@ -23,8 +23,8 @@ import android.os.Parcel; import android.platform.test.annotations.Presubmit; import android.text.TextUtils; +import androidx.test.ext.junit.runners.AndroidJUnit4; import androidx.test.filters.SmallTest; -import androidx.test.runner.AndroidJUnit4; import com.google.common.base.Strings; diff --git a/core/tests/coretests/src/android/app/NotificationChannelTest.java b/core/tests/coretests/src/android/app/NotificationChannelTest.java index 504f98f0ac49..c08e42b7179c 100644 --- a/core/tests/coretests/src/android/app/NotificationChannelTest.java +++ b/core/tests/coretests/src/android/app/NotificationChannelTest.java @@ -23,7 +23,6 @@ import static junit.framework.TestCase.assertFalse; import static junit.framework.TestCase.assertNull; import static junit.framework.TestCase.assertTrue; -import static org.junit.Assert.assertEquals; import static org.mockito.ArgumentMatchers.any; import static org.mockito.ArgumentMatchers.argThat; import static org.mockito.ArgumentMatchers.eq; @@ -31,7 +30,6 @@ import static org.mockito.Mockito.doAnswer; import static org.mockito.Mockito.mock; import static org.mockito.Mockito.when; -import android.annotation.FlaggedApi; import android.content.AttributionSource; import android.content.ContentProvider; import android.content.ContentResolver; @@ -54,8 +52,8 @@ import android.provider.MediaStore.Audio.AudioColumns; import android.test.mock.MockContentResolver; import android.util.Xml; +import androidx.test.ext.junit.runners.AndroidJUnit4; import androidx.test.filters.SmallTest; -import androidx.test.runner.AndroidJUnit4; import com.android.modules.utils.TypedXmlPullParser; import com.android.modules.utils.TypedXmlSerializer; diff --git a/core/tests/coretests/src/android/app/NotificationHistoryTest.java b/core/tests/coretests/src/android/app/NotificationHistoryTest.java index c44c1ebbed6b..38581e86b085 100644 --- a/core/tests/coretests/src/android/app/NotificationHistoryTest.java +++ b/core/tests/coretests/src/android/app/NotificationHistoryTest.java @@ -24,7 +24,7 @@ import android.os.Parcel; import android.platform.test.annotations.Presubmit; import androidx.test.InstrumentationRegistry; -import androidx.test.runner.AndroidJUnit4; +import androidx.test.ext.junit.runners.AndroidJUnit4; import org.junit.Test; import org.junit.runner.RunWith; diff --git a/core/tests/coretests/src/android/app/QueuedWorkTest.java b/core/tests/coretests/src/android/app/QueuedWorkTest.java index 70211870989f..230c9e86db6b 100644 --- a/core/tests/coretests/src/android/app/QueuedWorkTest.java +++ b/core/tests/coretests/src/android/app/QueuedWorkTest.java @@ -20,18 +20,18 @@ import static com.google.common.truth.Truth.assertThat; import android.platform.test.annotations.Presubmit; +import androidx.test.ext.junit.runners.AndroidJUnit4; import androidx.test.filters.SmallTest; -import androidx.test.runner.AndroidJUnit4; - -import java.util.concurrent.atomic.AtomicBoolean; -import java.util.concurrent.atomic.AtomicInteger; -import java.util.concurrent.Semaphore; import org.junit.After; import org.junit.Before; import org.junit.Test; import org.junit.runner.RunWith; +import java.util.concurrent.Semaphore; +import java.util.concurrent.atomic.AtomicBoolean; +import java.util.concurrent.atomic.AtomicInteger; + @RunWith(AndroidJUnit4.class) @Presubmit @SmallTest diff --git a/core/tests/coretests/src/android/app/activity/ActivityTransitionDrawableTest.java b/core/tests/coretests/src/android/app/activity/ActivityTransitionDrawableTest.java index 2c4e44303fe3..a50f524034bf 100644 --- a/core/tests/coretests/src/android/app/activity/ActivityTransitionDrawableTest.java +++ b/core/tests/coretests/src/android/app/activity/ActivityTransitionDrawableTest.java @@ -27,9 +27,9 @@ import android.transition.Fade; import android.view.View; import android.view.Window; +import androidx.test.ext.junit.runners.AndroidJUnit4; import androidx.test.filters.MediumTest; import androidx.test.rule.ActivityTestRule; -import androidx.test.runner.AndroidJUnit4; import org.junit.Rule; import org.junit.Test; diff --git a/core/tests/coretests/src/android/app/activity/RegisterComponentCallbacksTest.java b/core/tests/coretests/src/android/app/activity/RegisterComponentCallbacksTest.java index fd1add9b4468..5958d15be21b 100644 --- a/core/tests/coretests/src/android/app/activity/RegisterComponentCallbacksTest.java +++ b/core/tests/coretests/src/android/app/activity/RegisterComponentCallbacksTest.java @@ -36,8 +36,8 @@ import android.platform.test.annotations.Presubmit; import androidx.test.core.app.ActivityScenario; import androidx.test.ext.junit.rules.ActivityScenarioRule; +import androidx.test.ext.junit.runners.AndroidJUnit4; import androidx.test.filters.SmallTest; -import androidx.test.runner.AndroidJUnit4; import org.junit.Rule; import org.junit.Test; diff --git a/core/tests/coretests/src/android/app/activity/ServiceTest.java b/core/tests/coretests/src/android/app/activity/ServiceTest.java index 3f3d6a3bff34..4e3b2af919e9 100644 --- a/core/tests/coretests/src/android/app/activity/ServiceTest.java +++ b/core/tests/coretests/src/android/app/activity/ServiceTest.java @@ -157,6 +157,21 @@ public class ServiceTest extends TestCase { assertThat(mCurrentConnection.takePid(), is(NOT_STARTED)); } + @Test + public void testRestart_stickyStartedService_unbindHappenedAfterRestart_restarted() { + final int servicePid = startService(Service.START_STICKY); + assertThat(servicePid, not(NOT_STARTED)); + assertThat(bindService(0 /* flags */), is(servicePid)); + + final int restartedServicePid = waitForServiceStarted( + () -> { + Process.killProcess(servicePid); + mContext.unbindService(mCurrentConnection); + mCurrentConnection = null; + }); + assertThat(restartedServicePid, not(NOT_STARTED)); + } + /** @return The pid of the started service. */ private int startService(int code) { return waitForServiceStarted( diff --git a/core/tests/coretests/src/android/app/admin/PackagePolicyTest.java b/core/tests/coretests/src/android/app/admin/PackagePolicyTest.java index d8298fdb284d..c648fd2bfb8f 100644 --- a/core/tests/coretests/src/android/app/admin/PackagePolicyTest.java +++ b/core/tests/coretests/src/android/app/admin/PackagePolicyTest.java @@ -29,8 +29,8 @@ import android.os.Parcel; import android.platform.test.annotations.Presubmit; import android.util.ArraySet; +import androidx.test.ext.junit.runners.AndroidJUnit4; import androidx.test.filters.SmallTest; -import androidx.test.runner.AndroidJUnit4; import org.junit.Test; import org.junit.runner.RunWith; diff --git a/core/tests/coretests/src/android/app/admin/PasswordPolicyTest.java b/core/tests/coretests/src/android/app/admin/PasswordPolicyTest.java index f1be173b3677..2d0dd9fc7d82 100644 --- a/core/tests/coretests/src/android/app/admin/PasswordPolicyTest.java +++ b/core/tests/coretests/src/android/app/admin/PasswordPolicyTest.java @@ -36,8 +36,8 @@ import android.app.admin.PasswordMetrics; import android.app.admin.PasswordPolicy; import android.platform.test.annotations.Presubmit; +import androidx.test.ext.junit.runners.AndroidJUnit4; import androidx.test.filters.SmallTest; -import androidx.test.runner.AndroidJUnit4; import org.junit.Test; import org.junit.runner.RunWith; diff --git a/core/tests/coretests/src/android/app/assist/AssistStructureTest.java b/core/tests/coretests/src/android/app/assist/AssistStructureTest.java index 1f2788c4b11b..a28b2f66aaa8 100644 --- a/core/tests/coretests/src/android/app/assist/AssistStructureTest.java +++ b/core/tests/coretests/src/android/app/assist/AssistStructureTest.java @@ -49,8 +49,8 @@ import android.widget.TextView; import androidx.annotation.NonNull; import androidx.test.InstrumentationRegistry; +import androidx.test.ext.junit.runners.AndroidJUnit4; import androidx.test.rule.ActivityTestRule; -import androidx.test.runner.AndroidJUnit4; import org.junit.Before; import org.junit.Test; diff --git a/core/tests/coretests/src/android/app/backup/BackupAgentTest.java b/core/tests/coretests/src/android/app/backup/BackupAgentTest.java index cd5deb6c4293..93bbb3ad4e7e 100644 --- a/core/tests/coretests/src/android/app/backup/BackupAgentTest.java +++ b/core/tests/coretests/src/android/app/backup/BackupAgentTest.java @@ -32,7 +32,7 @@ import android.platform.test.annotations.Presubmit; import android.platform.test.flag.junit.SetFlagsRule; import android.util.ArraySet; -import androidx.test.runner.AndroidJUnit4; +import androidx.test.ext.junit.runners.AndroidJUnit4; import com.android.server.backup.Flags; diff --git a/core/tests/coretests/src/android/app/backup/BackupManagerMonitorWrapperTest.java b/core/tests/coretests/src/android/app/backup/BackupManagerMonitorWrapperTest.java index 1f5e0cf52d5c..3620a0c2beb9 100644 --- a/core/tests/coretests/src/android/app/backup/BackupManagerMonitorWrapperTest.java +++ b/core/tests/coretests/src/android/app/backup/BackupManagerMonitorWrapperTest.java @@ -25,7 +25,7 @@ import static org.mockito.Mockito.verify; import android.os.Bundle; import android.platform.test.annotations.Presubmit; -import androidx.test.runner.AndroidJUnit4; +import androidx.test.ext.junit.runners.AndroidJUnit4; import org.junit.Before; import org.junit.Test; diff --git a/core/tests/coretests/src/android/app/backup/BackupManagerTest.java b/core/tests/coretests/src/android/app/backup/BackupManagerTest.java index 567ca0148404..88994c98e711 100644 --- a/core/tests/coretests/src/android/app/backup/BackupManagerTest.java +++ b/core/tests/coretests/src/android/app/backup/BackupManagerTest.java @@ -30,7 +30,7 @@ import android.os.RemoteException; import android.os.UserHandle; import android.platform.test.annotations.Presubmit; -import androidx.test.runner.AndroidJUnit4; +import androidx.test.ext.junit.runners.AndroidJUnit4; import org.junit.Before; import org.junit.Test; diff --git a/core/tests/coretests/src/android/app/backup/BackupRestoreEventLoggerTest.java b/core/tests/coretests/src/android/app/backup/BackupRestoreEventLoggerTest.java index 0aefef2cd2d3..7b41217d6200 100644 --- a/core/tests/coretests/src/android/app/backup/BackupRestoreEventLoggerTest.java +++ b/core/tests/coretests/src/android/app/backup/BackupRestoreEventLoggerTest.java @@ -28,7 +28,7 @@ import android.os.Parcel; import android.platform.test.annotations.Presubmit; import android.platform.test.flag.junit.SetFlagsRule; -import androidx.test.runner.AndroidJUnit4; +import androidx.test.ext.junit.runners.AndroidJUnit4; import com.android.server.backup.Flags; diff --git a/core/tests/coretests/src/android/app/compat/CompatChangesTest.java b/core/tests/coretests/src/android/app/compat/CompatChangesTest.java index fbd02eddbcf8..8fd21c8c391b 100644 --- a/core/tests/coretests/src/android/app/compat/CompatChangesTest.java +++ b/core/tests/coretests/src/android/app/compat/CompatChangesTest.java @@ -25,8 +25,8 @@ import android.os.UserHandle; import android.platform.test.annotations.Presubmit; import androidx.test.InstrumentationRegistry; +import androidx.test.ext.junit.runners.AndroidJUnit4; import androidx.test.filters.SmallTest; -import androidx.test.runner.AndroidJUnit4; import libcore.junit.util.compat.CoreCompatChangeRule.DisableCompatChanges; import libcore.junit.util.compat.CoreCompatChangeRule.EnableCompatChanges; diff --git a/core/tests/coretests/src/android/app/people/PeopleManagerTest.java b/core/tests/coretests/src/android/app/people/PeopleManagerTest.java index a2afc777a552..1296d32b21cd 100644 --- a/core/tests/coretests/src/android/app/people/PeopleManagerTest.java +++ b/core/tests/coretests/src/android/app/people/PeopleManagerTest.java @@ -31,7 +31,7 @@ import android.os.test.TestLooper; import android.util.Pair; import androidx.test.InstrumentationRegistry; -import androidx.test.runner.AndroidJUnit4; +import androidx.test.ext.junit.runners.AndroidJUnit4; import org.junit.Before; import org.junit.Test; diff --git a/core/tests/coretests/src/android/app/people/PeopleSpaceTileTest.java b/core/tests/coretests/src/android/app/people/PeopleSpaceTileTest.java index 5cee2c1389e4..a9d1d3588513 100644 --- a/core/tests/coretests/src/android/app/people/PeopleSpaceTileTest.java +++ b/core/tests/coretests/src/android/app/people/PeopleSpaceTileTest.java @@ -43,8 +43,8 @@ import android.os.Parcel; import android.os.UserHandle; import androidx.test.InstrumentationRegistry; +import androidx.test.ext.junit.runners.AndroidJUnit4; import androidx.test.filters.SmallTest; -import androidx.test.runner.AndroidJUnit4; import com.google.common.collect.ImmutableList; diff --git a/core/tests/coretests/src/android/app/usage/EventListTest.java b/core/tests/coretests/src/android/app/usage/EventListTest.java index 685fcae46553..d5a685818a4e 100644 --- a/core/tests/coretests/src/android/app/usage/EventListTest.java +++ b/core/tests/coretests/src/android/app/usage/EventListTest.java @@ -22,8 +22,8 @@ import static org.junit.Assert.fail; import android.util.Log; +import androidx.test.ext.junit.runners.AndroidJUnit4; import androidx.test.filters.SmallTest; -import androidx.test.runner.AndroidJUnit4; import org.junit.Test; import org.junit.runner.RunWith; diff --git a/core/tests/coretests/src/android/app/usage/ParcelableUsageEventListTest.java b/core/tests/coretests/src/android/app/usage/ParcelableUsageEventListTest.java index da40f2adec6f..1c35a64ac575 100644 --- a/core/tests/coretests/src/android/app/usage/ParcelableUsageEventListTest.java +++ b/core/tests/coretests/src/android/app/usage/ParcelableUsageEventListTest.java @@ -30,8 +30,8 @@ import android.content.res.Configuration; import android.os.Parcel; import android.os.PersistableBundle; +import androidx.test.ext.junit.runners.AndroidJUnit4; import androidx.test.filters.LargeTest; -import androidx.test.runner.AndroidJUnit4; import org.junit.Test; import org.junit.runner.RunWith; diff --git a/core/tests/coretests/src/android/app/usage/UsageEventsQueryTest.java b/core/tests/coretests/src/android/app/usage/UsageEventsQueryTest.java index 55168458d49a..97d2819f1f09 100644 --- a/core/tests/coretests/src/android/app/usage/UsageEventsQueryTest.java +++ b/core/tests/coretests/src/android/app/usage/UsageEventsQueryTest.java @@ -25,8 +25,8 @@ import android.platform.test.annotations.RequiresFlagsEnabled; import android.platform.test.flag.junit.CheckFlagsRule; import android.platform.test.flag.junit.DeviceFlagsValueProvider; +import androidx.test.ext.junit.runners.AndroidJUnit4; import androidx.test.filters.SmallTest; -import androidx.test.runner.AndroidJUnit4; import org.junit.Rule; import org.junit.Test; diff --git a/core/tests/coretests/src/android/app/usage/UsageStatsPersistenceTest.java b/core/tests/coretests/src/android/app/usage/UsageStatsPersistenceTest.java index 3618543e3ae3..ad6b1b8919ec 100644 --- a/core/tests/coretests/src/android/app/usage/UsageStatsPersistenceTest.java +++ b/core/tests/coretests/src/android/app/usage/UsageStatsPersistenceTest.java @@ -18,8 +18,8 @@ package android.app.usage; import static junit.framework.Assert.fail; +import androidx.test.ext.junit.runners.AndroidJUnit4; import androidx.test.filters.SmallTest; -import androidx.test.runner.AndroidJUnit4; import com.android.internal.util.ArrayUtils; diff --git a/core/tests/coretests/src/android/app/usage/UsageStatsTest.java b/core/tests/coretests/src/android/app/usage/UsageStatsTest.java index f72808067df5..69a7a68bf241 100644 --- a/core/tests/coretests/src/android/app/usage/UsageStatsTest.java +++ b/core/tests/coretests/src/android/app/usage/UsageStatsTest.java @@ -38,8 +38,8 @@ import android.os.Parcel; import android.os.UserHandle; import androidx.test.InstrumentationRegistry; +import androidx.test.ext.junit.runners.AndroidJUnit4; import androidx.test.filters.SmallTest; -import androidx.test.runner.AndroidJUnit4; import androidx.test.uiautomator.UiDevice; import org.junit.Before; diff --git a/core/tests/coretests/src/android/companion/virtual/audio/VirtualAudioSessionTest.java b/core/tests/coretests/src/android/companion/virtual/audio/VirtualAudioSessionTest.java index e025fae4b909..b91263ea6b3c 100644 --- a/core/tests/coretests/src/android/companion/virtual/audio/VirtualAudioSessionTest.java +++ b/core/tests/coretests/src/android/companion/virtual/audio/VirtualAudioSessionTest.java @@ -35,7 +35,7 @@ import android.media.AudioRecordingConfiguration; import android.platform.test.annotations.Presubmit; import androidx.test.InstrumentationRegistry; -import androidx.test.runner.AndroidJUnit4; +import androidx.test.ext.junit.runners.AndroidJUnit4; import org.junit.Before; import org.junit.Rule; diff --git a/core/tests/coretests/src/android/debug/AdbNotificationsTest.java b/core/tests/coretests/src/android/debug/AdbNotificationsTest.java index 3496e2c7fea3..10eeb35855b9 100644 --- a/core/tests/coretests/src/android/debug/AdbNotificationsTest.java +++ b/core/tests/coretests/src/android/debug/AdbNotificationsTest.java @@ -25,8 +25,8 @@ import android.platform.test.annotations.Presubmit; import android.text.TextUtils; import androidx.test.InstrumentationRegistry; +import androidx.test.ext.junit.runners.AndroidJUnit4; import androidx.test.filters.SmallTest; -import androidx.test.runner.AndroidJUnit4; import org.junit.Before; import org.junit.Test; diff --git a/core/tests/coretests/src/android/graphics/FontListParserTest.java b/core/tests/coretests/src/android/graphics/FontListParserTest.java index 5f96c1789015..52f53ddb4356 100644 --- a/core/tests/coretests/src/android/graphics/FontListParserTest.java +++ b/core/tests/coretests/src/android/graphics/FontListParserTest.java @@ -16,16 +16,16 @@ package android.graphics; +import static android.graphics.fonts.FontFamily.Builder.VARIABLE_FONT_FAMILY_TYPE_NONE; +import static android.graphics.fonts.FontFamily.Builder.VARIABLE_FONT_FAMILY_TYPE_SINGLE_FONT_WGHT_ITAL; +import static android.graphics.fonts.FontFamily.Builder.VARIABLE_FONT_FAMILY_TYPE_SINGLE_FONT_WGHT_ONLY; +import static android.graphics.fonts.FontFamily.Builder.VARIABLE_FONT_FAMILY_TYPE_TWO_FONTS_WGHT; import static android.graphics.fonts.FontStyle.FONT_SLANT_ITALIC; import static android.graphics.fonts.FontStyle.FONT_SLANT_UPRIGHT; import static android.graphics.fonts.FontStyle.FONT_WEIGHT_NORMAL; import static android.text.FontConfig.FontFamily.VARIANT_COMPACT; import static android.text.FontConfig.FontFamily.VARIANT_DEFAULT; import static android.text.FontConfig.FontFamily.VARIANT_ELEGANT; -import static android.graphics.fonts.FontFamily.Builder.VARIABLE_FONT_FAMILY_TYPE_NONE; -import static android.graphics.fonts.FontFamily.Builder.VARIABLE_FONT_FAMILY_TYPE_SINGLE_FONT_WGHT_ONLY; -import static android.graphics.fonts.FontFamily.Builder.VARIABLE_FONT_FAMILY_TYPE_SINGLE_FONT_WGHT_ITAL; -import static android.graphics.fonts.FontFamily.Builder.VARIABLE_FONT_FAMILY_TYPE_TWO_FONTS_WGHT; import static com.google.common.truth.Truth.assertThat; @@ -38,8 +38,8 @@ import android.os.LocaleList; import android.text.FontConfig; import android.util.Xml; +import androidx.test.ext.junit.runners.AndroidJUnit4; import androidx.test.filters.SmallTest; -import androidx.test.runner.AndroidJUnit4; import org.junit.Test; import org.junit.runner.RunWith; diff --git a/core/tests/coretests/src/android/graphics/RectTest.java b/core/tests/coretests/src/android/graphics/RectTest.java index 2918f44ad65d..d0cb5d5ea416 100644 --- a/core/tests/coretests/src/android/graphics/RectTest.java +++ b/core/tests/coretests/src/android/graphics/RectTest.java @@ -24,8 +24,8 @@ import static org.junit.Assert.assertNull; import android.platform.test.annotations.Presubmit; +import androidx.test.ext.junit.runners.AndroidJUnit4; import androidx.test.filters.SmallTest; -import androidx.test.runner.AndroidJUnit4; import org.junit.Test; import org.junit.runner.RunWith; diff --git a/core/tests/coretests/src/android/graphics/TypefaceEqualsTest.java b/core/tests/coretests/src/android/graphics/TypefaceEqualsTest.java index 6ae7eb72fab2..a94f41279392 100644 --- a/core/tests/coretests/src/android/graphics/TypefaceEqualsTest.java +++ b/core/tests/coretests/src/android/graphics/TypefaceEqualsTest.java @@ -23,8 +23,8 @@ import android.content.res.AssetManager; import android.graphics.fonts.Font; import androidx.test.InstrumentationRegistry; +import androidx.test.ext.junit.runners.AndroidJUnit4; import androidx.test.filters.SmallTest; -import androidx.test.runner.AndroidJUnit4; import org.junit.Test; import org.junit.runner.RunWith; diff --git a/core/tests/coretests/src/android/graphics/TypefaceSystemFallbackTest.java b/core/tests/coretests/src/android/graphics/TypefaceSystemFallbackTest.java index 0d687b24a4e5..10aed8d51d09 100644 --- a/core/tests/coretests/src/android/graphics/TypefaceSystemFallbackTest.java +++ b/core/tests/coretests/src/android/graphics/TypefaceSystemFallbackTest.java @@ -39,8 +39,8 @@ import android.text.FontConfig; import android.util.ArrayMap; import androidx.test.InstrumentationRegistry; +import androidx.test.ext.junit.runners.AndroidJUnit4; import androidx.test.filters.SmallTest; -import androidx.test.runner.AndroidJUnit4; import org.junit.After; import org.junit.Before; diff --git a/core/tests/coretests/src/android/graphics/TypefaceTest.java b/core/tests/coretests/src/android/graphics/TypefaceTest.java index 6bf8f5678b33..80efa511d163 100644 --- a/core/tests/coretests/src/android/graphics/TypefaceTest.java +++ b/core/tests/coretests/src/android/graphics/TypefaceTest.java @@ -30,10 +30,10 @@ import android.text.FontConfig; import android.util.ArrayMap; import androidx.test.InstrumentationRegistry; +import androidx.test.ext.junit.runners.AndroidJUnit4; import androidx.test.filters.LargeTest; import androidx.test.filters.MediumTest; import androidx.test.filters.SmallTest; -import androidx.test.runner.AndroidJUnit4; import com.android.frameworks.coretests.R; diff --git a/core/tests/coretests/src/android/graphics/drawable/DrawableWrapperTest.java b/core/tests/coretests/src/android/graphics/drawable/DrawableWrapperTest.java index d0a6ff9251cc..4991cd0a1347 100644 --- a/core/tests/coretests/src/android/graphics/drawable/DrawableWrapperTest.java +++ b/core/tests/coretests/src/android/graphics/drawable/DrawableWrapperTest.java @@ -25,8 +25,8 @@ import android.graphics.PorterDuff.Mode; import android.graphics.PorterDuffXfermode; import android.graphics.Xfermode; +import androidx.test.ext.junit.runners.AndroidJUnit4; import androidx.test.filters.SmallTest; -import androidx.test.runner.AndroidJUnit4; import org.junit.Test; import org.junit.runner.RunWith; diff --git a/core/tests/coretests/src/android/hardware/display/AmbientBrightnessDayStatsTest.java b/core/tests/coretests/src/android/hardware/display/AmbientBrightnessDayStatsTest.java index 0a25bd7e3f2c..244024da89b3 100644 --- a/core/tests/coretests/src/android/hardware/display/AmbientBrightnessDayStatsTest.java +++ b/core/tests/coretests/src/android/hardware/display/AmbientBrightnessDayStatsTest.java @@ -24,8 +24,8 @@ import static org.junit.Assert.fail; import android.os.Parcel; +import androidx.test.ext.junit.runners.AndroidJUnit4; import androidx.test.filters.SmallTest; -import androidx.test.runner.AndroidJUnit4; import org.junit.Test; import org.junit.runner.RunWith; diff --git a/core/tests/coretests/src/android/hardware/display/BrightnessConfigurationTest.java b/core/tests/coretests/src/android/hardware/display/BrightnessConfigurationTest.java index 1c7ab7428ee7..9f12e5121999 100644 --- a/core/tests/coretests/src/android/hardware/display/BrightnessConfigurationTest.java +++ b/core/tests/coretests/src/android/hardware/display/BrightnessConfigurationTest.java @@ -25,8 +25,8 @@ import android.os.Parcel; import android.util.Pair; import android.util.Xml; +import androidx.test.ext.junit.runners.AndroidJUnit4; import androidx.test.filters.SmallTest; -import androidx.test.runner.AndroidJUnit4; import com.android.modules.utils.TypedXmlPullParser; import com.android.modules.utils.TypedXmlSerializer; diff --git a/core/tests/coretests/src/android/hardware/display/DisplayManagerGlobalTest.java b/core/tests/coretests/src/android/hardware/display/DisplayManagerGlobalTest.java index 969ae8e819da..5a0dacb38865 100644 --- a/core/tests/coretests/src/android/hardware/display/DisplayManagerGlobalTest.java +++ b/core/tests/coretests/src/android/hardware/display/DisplayManagerGlobalTest.java @@ -31,8 +31,8 @@ import android.platform.test.annotations.Presubmit; import android.view.DisplayInfo; import androidx.test.InstrumentationRegistry; +import androidx.test.ext.junit.runners.AndroidJUnit4; import androidx.test.filters.SmallTest; -import androidx.test.runner.AndroidJUnit4; import org.junit.Before; import org.junit.Test; diff --git a/core/tests/coretests/src/android/hardware/input/InputFlagsTest.java b/core/tests/coretests/src/android/hardware/input/InputFlagsTest.java index 5aeab42eaaea..b4f1deebd796 100644 --- a/core/tests/coretests/src/android/hardware/input/InputFlagsTest.java +++ b/core/tests/coretests/src/android/hardware/input/InputFlagsTest.java @@ -21,8 +21,8 @@ import static com.android.hardware.input.Flags.keyboardLayoutPreviewFlag; import android.platform.test.annotations.Presubmit; +import androidx.test.ext.junit.runners.AndroidJUnit4; import androidx.test.filters.SmallTest; -import androidx.test.runner.AndroidJUnit4; import org.junit.Test; import org.junit.runner.RunWith; diff --git a/core/tests/coretests/src/android/net/NetworkKeyTest.java b/core/tests/coretests/src/android/net/NetworkKeyTest.java index b13bcd1311f6..444ed51fa823 100644 --- a/core/tests/coretests/src/android/net/NetworkKeyTest.java +++ b/core/tests/coretests/src/android/net/NetworkKeyTest.java @@ -25,7 +25,7 @@ import android.net.wifi.ScanResult; import android.net.wifi.WifiInfo; import android.net.wifi.WifiManager; -import androidx.test.runner.AndroidJUnit4; +import androidx.test.ext.junit.runners.AndroidJUnit4; import org.junit.Before; import org.junit.Test; diff --git a/core/tests/coretests/src/android/net/NetworkRecommendationProviderTest.java b/core/tests/coretests/src/android/net/NetworkRecommendationProviderTest.java index 3e45a79951d3..46f22cec4213 100644 --- a/core/tests/coretests/src/android/net/NetworkRecommendationProviderTest.java +++ b/core/tests/coretests/src/android/net/NetworkRecommendationProviderTest.java @@ -26,7 +26,7 @@ import static org.mockito.Matchers.eq; import android.Manifest.permission; import android.content.Context; -import androidx.test.runner.AndroidJUnit4; +import androidx.test.ext.junit.runners.AndroidJUnit4; import org.junit.Before; import org.junit.Test; diff --git a/core/tests/coretests/src/android/net/SSLCertificateSocketFactoryTest.java b/core/tests/coretests/src/android/net/SSLCertificateSocketFactoryTest.java index bc12e727c5f0..7413ede92914 100644 --- a/core/tests/coretests/src/android/net/SSLCertificateSocketFactoryTest.java +++ b/core/tests/coretests/src/android/net/SSLCertificateSocketFactoryTest.java @@ -19,7 +19,7 @@ package android.net; import static org.junit.Assert.assertTrue; import static org.junit.Assert.fail; -import androidx.test.runner.AndroidJUnit4; +import androidx.test.ext.junit.runners.AndroidJUnit4; import org.junit.Test; import org.junit.runner.RunWith; diff --git a/core/tests/coretests/src/android/net/ScoredNetworkTest.java b/core/tests/coretests/src/android/net/ScoredNetworkTest.java index d984d86e1147..63eeaa1e97e0 100644 --- a/core/tests/coretests/src/android/net/ScoredNetworkTest.java +++ b/core/tests/coretests/src/android/net/ScoredNetworkTest.java @@ -26,7 +26,7 @@ import static org.junit.Assert.fail; import android.os.Bundle; import android.os.Parcel; -import androidx.test.runner.AndroidJUnit4; +import androidx.test.ext.junit.runners.AndroidJUnit4; import org.junit.Test; import org.junit.runner.RunWith; diff --git a/core/tests/coretests/src/android/net/SntpClientTest.java b/core/tests/coretests/src/android/net/SntpClientTest.java index 267fc2b636d6..024d614814a1 100644 --- a/core/tests/coretests/src/android/net/SntpClientTest.java +++ b/core/tests/coretests/src/android/net/SntpClientTest.java @@ -29,7 +29,7 @@ import android.net.sntp.Timestamp64; import android.platform.test.annotations.Presubmit; import android.util.Log; -import androidx.test.runner.AndroidJUnit4; +import androidx.test.ext.junit.runners.AndroidJUnit4; import libcore.util.HexEncoding; diff --git a/core/tests/coretests/src/android/net/sntp/Duration64Test.java b/core/tests/coretests/src/android/net/sntp/Duration64Test.java index b2285962f82d..b177e18a5d8a 100644 --- a/core/tests/coretests/src/android/net/sntp/Duration64Test.java +++ b/core/tests/coretests/src/android/net/sntp/Duration64Test.java @@ -23,7 +23,7 @@ import static org.junit.Assert.assertTrue; import android.platform.test.annotations.Presubmit; -import androidx.test.runner.AndroidJUnit4; +import androidx.test.ext.junit.runners.AndroidJUnit4; import org.junit.Test; import org.junit.runner.RunWith; diff --git a/core/tests/coretests/src/android/net/sntp/Timestamp64Test.java b/core/tests/coretests/src/android/net/sntp/Timestamp64Test.java index 200c80e81588..9f95132a8437 100644 --- a/core/tests/coretests/src/android/net/sntp/Timestamp64Test.java +++ b/core/tests/coretests/src/android/net/sntp/Timestamp64Test.java @@ -23,7 +23,7 @@ import static org.junit.Assert.fail; import android.platform.test.annotations.Presubmit; -import androidx.test.runner.AndroidJUnit4; +import androidx.test.ext.junit.runners.AndroidJUnit4; import org.junit.Test; import org.junit.runner.RunWith; diff --git a/core/tests/coretests/src/android/os/LocaleListTest.java b/core/tests/coretests/src/android/os/LocaleListTest.java index 251e00fb68f2..0b8aff0c5d88 100644 --- a/core/tests/coretests/src/android/os/LocaleListTest.java +++ b/core/tests/coretests/src/android/os/LocaleListTest.java @@ -20,7 +20,6 @@ import static org.junit.Assert.assertEquals; import static org.junit.Assert.assertSame; import static org.junit.Assert.fail; -import android.platform.test.annotations.IgnoreUnderRavenwood; import android.platform.test.ravenwood.RavenwoodRule; import androidx.test.ext.junit.runners.AndroidJUnit4; @@ -33,7 +32,6 @@ import org.junit.runner.RunWith; import java.util.Locale; @RunWith(AndroidJUnit4.class) -@IgnoreUnderRavenwood(blockedBy = LocaleList.class) public class LocaleListTest { @Rule public final RavenwoodRule mRavenwood = new RavenwoodRule(); diff --git a/core/tests/coretests/src/android/preference/PreferenceIconSpaceTest.java b/core/tests/coretests/src/android/preference/PreferenceIconSpaceTest.java index 0deb77e60a51..55a347ec2227 100644 --- a/core/tests/coretests/src/android/preference/PreferenceIconSpaceTest.java +++ b/core/tests/coretests/src/android/preference/PreferenceIconSpaceTest.java @@ -27,8 +27,8 @@ import android.view.ViewGroup; import android.widget.ImageView; import androidx.test.InstrumentationRegistry; +import androidx.test.ext.junit.runners.AndroidJUnit4; import androidx.test.filters.SmallTest; -import androidx.test.runner.AndroidJUnit4; import org.junit.Before; import org.junit.Test; diff --git a/core/tests/coretests/src/android/print/IPrintManagerParametersTest.java b/core/tests/coretests/src/android/print/IPrintManagerParametersTest.java index c25aa51c6b1e..746c8cafe1e7 100644 --- a/core/tests/coretests/src/android/print/IPrintManagerParametersTest.java +++ b/core/tests/coretests/src/android/print/IPrintManagerParametersTest.java @@ -42,9 +42,9 @@ import android.print.test.services.PrinterDiscoverySessionCallbacks; import android.print.test.services.StubbablePrinterDiscoverySession; import android.printservice.recommendation.IRecommendationsChangeListener; +import androidx.test.ext.junit.runners.AndroidJUnit4; import androidx.test.filters.LargeTest; import androidx.test.filters.MediumTest; -import androidx.test.runner.AndroidJUnit4; import androidx.test.uiautomator.UiDevice; import org.junit.Before; diff --git a/core/tests/coretests/src/android/provider/DeviceConfigServiceManagerTest.java b/core/tests/coretests/src/android/provider/DeviceConfigServiceManagerTest.java index e20258a625dd..a60746f4047c 100644 --- a/core/tests/coretests/src/android/provider/DeviceConfigServiceManagerTest.java +++ b/core/tests/coretests/src/android/provider/DeviceConfigServiceManagerTest.java @@ -23,8 +23,8 @@ import static org.junit.Assume.assumeTrue; import android.platform.test.annotations.Presubmit; +import androidx.test.ext.junit.runners.AndroidJUnit4; import androidx.test.filters.SmallTest; -import androidx.test.runner.AndroidJUnit4; import org.junit.Before; import org.junit.Test; diff --git a/core/tests/coretests/src/android/provider/DeviceConfigTest.java b/core/tests/coretests/src/android/provider/DeviceConfigTest.java index 9300d1e5cb95..681396e6011a 100644 --- a/core/tests/coretests/src/android/provider/DeviceConfigTest.java +++ b/core/tests/coretests/src/android/provider/DeviceConfigTest.java @@ -29,9 +29,9 @@ import android.os.Bundle; import android.platform.test.annotations.Presubmit; import androidx.test.InstrumentationRegistry; +import androidx.test.ext.junit.runners.AndroidJUnit4; import androidx.test.filters.FlakyTest; import androidx.test.filters.SmallTest; -import androidx.test.runner.AndroidJUnit4; import org.junit.After; import org.junit.Assert; diff --git a/core/tests/coretests/src/android/provider/FontsContractE2ETest.java b/core/tests/coretests/src/android/provider/FontsContractE2ETest.java index 7e02be85f01a..401017129fa3 100644 --- a/core/tests/coretests/src/android/provider/FontsContractE2ETest.java +++ b/core/tests/coretests/src/android/provider/FontsContractE2ETest.java @@ -33,8 +33,8 @@ import android.os.Handler; import android.provider.FontsContract.FontFamilyResult; import androidx.test.InstrumentationRegistry; +import androidx.test.ext.junit.runners.AndroidJUnit4; import androidx.test.filters.SmallTest; -import androidx.test.runner.AndroidJUnit4; import org.junit.After; import org.junit.Before; diff --git a/core/tests/coretests/src/android/service/controls/ControlProviderServiceTest.java b/core/tests/coretests/src/android/service/controls/ControlProviderServiceTest.java index 4d4469011c06..6eaf2e4890a3 100644 --- a/core/tests/coretests/src/android/service/controls/ControlProviderServiceTest.java +++ b/core/tests/coretests/src/android/service/controls/ControlProviderServiceTest.java @@ -45,9 +45,9 @@ import android.service.controls.actions.ControlAction; import android.service.controls.actions.ControlActionWrapper; import android.service.controls.templates.ThumbnailTemplate; +import androidx.test.ext.junit.runners.AndroidJUnit4; import androidx.test.filters.SmallTest; import androidx.test.platform.app.InstrumentationRegistry; -import androidx.test.runner.AndroidJUnit4; import com.android.internal.R; diff --git a/core/tests/coretests/src/android/service/controls/actions/ControlActionTest.java b/core/tests/coretests/src/android/service/controls/actions/ControlActionTest.java index d8088b7735ad..44bdc53af1d4 100644 --- a/core/tests/coretests/src/android/service/controls/actions/ControlActionTest.java +++ b/core/tests/coretests/src/android/service/controls/actions/ControlActionTest.java @@ -23,8 +23,8 @@ import static org.junit.Assert.assertNotNull; import android.os.Parcel; +import androidx.test.ext.junit.runners.AndroidJUnit4; import androidx.test.filters.SmallTest; -import androidx.test.runner.AndroidJUnit4; import org.junit.Test; import org.junit.runner.RunWith; diff --git a/core/tests/coretests/src/android/service/controls/templates/ControlTemplateTest.java b/core/tests/coretests/src/android/service/controls/templates/ControlTemplateTest.java index 91a3ba7d0e74..73b6f6485db1 100644 --- a/core/tests/coretests/src/android/service/controls/templates/ControlTemplateTest.java +++ b/core/tests/coretests/src/android/service/controls/templates/ControlTemplateTest.java @@ -25,8 +25,8 @@ import android.annotation.DrawableRes; import android.graphics.drawable.Icon; import android.os.Parcel; +import androidx.test.ext.junit.runners.AndroidJUnit4; import androidx.test.filters.SmallTest; -import androidx.test.runner.AndroidJUnit4; import com.android.frameworks.coretests.R; diff --git a/core/tests/coretests/src/android/service/euicc/EuiccProfileInfoTest.java b/core/tests/coretests/src/android/service/euicc/EuiccProfileInfoTest.java index 6792d0b91084..f4206c85b6e6 100644 --- a/core/tests/coretests/src/android/service/euicc/EuiccProfileInfoTest.java +++ b/core/tests/coretests/src/android/service/euicc/EuiccProfileInfoTest.java @@ -26,8 +26,8 @@ import android.os.Parcel; import android.service.carrier.CarrierIdentifier; import android.telephony.UiccAccessRule; +import androidx.test.ext.junit.runners.AndroidJUnit4; import androidx.test.filters.SmallTest; -import androidx.test.runner.AndroidJUnit4; import org.junit.Test; import org.junit.runner.RunWith; diff --git a/core/tests/coretests/src/android/service/notification/NotificationListenerFilterTest.java b/core/tests/coretests/src/android/service/notification/NotificationListenerFilterTest.java index a121941e7b73..44456e94dd59 100644 --- a/core/tests/coretests/src/android/service/notification/NotificationListenerFilterTest.java +++ b/core/tests/coretests/src/android/service/notification/NotificationListenerFilterTest.java @@ -27,8 +27,8 @@ import android.content.pm.VersionedPackage; import android.os.Parcel; import android.util.ArraySet; +import androidx.test.ext.junit.runners.AndroidJUnit4; import androidx.test.filters.SmallTest; -import androidx.test.runner.AndroidJUnit4; import org.junit.Test; import org.junit.runner.RunWith; diff --git a/core/tests/coretests/src/android/service/notification/StatusBarNotificationTest.java b/core/tests/coretests/src/android/service/notification/StatusBarNotificationTest.java index 76c9f8892105..504240812559 100644 --- a/core/tests/coretests/src/android/service/notification/StatusBarNotificationTest.java +++ b/core/tests/coretests/src/android/service/notification/StatusBarNotificationTest.java @@ -37,8 +37,8 @@ import android.metrics.LogMaker; import android.os.UserHandle; import androidx.test.InstrumentationRegistry; +import androidx.test.ext.junit.runners.AndroidJUnit4; import androidx.test.filters.SmallTest; -import androidx.test.runner.AndroidJUnit4; import com.android.internal.logging.nano.MetricsProto.MetricsEvent; diff --git a/core/tests/coretests/src/android/service/quicksettings/TileTest.java b/core/tests/coretests/src/android/service/quicksettings/TileTest.java index ca6c3b443aa6..43f9122bf3da 100644 --- a/core/tests/coretests/src/android/service/quicksettings/TileTest.java +++ b/core/tests/coretests/src/android/service/quicksettings/TileTest.java @@ -18,8 +18,8 @@ package android.service.quicksettings; import static com.google.common.truth.Truth.assertThat; +import androidx.test.ext.junit.runners.AndroidJUnit4; import androidx.test.filters.SmallTest; -import androidx.test.runner.AndroidJUnit4; import org.junit.Test; import org.junit.runner.RunWith; diff --git a/core/tests/coretests/src/android/service/settings/suggestions/SuggestionServiceTest.java b/core/tests/coretests/src/android/service/settings/suggestions/SuggestionServiceTest.java index 64edda5ee879..85659d68c5a5 100644 --- a/core/tests/coretests/src/android/service/settings/suggestions/SuggestionServiceTest.java +++ b/core/tests/coretests/src/android/service/settings/suggestions/SuggestionServiceTest.java @@ -23,9 +23,9 @@ import android.os.IBinder; import android.os.RemoteException; import androidx.test.InstrumentationRegistry; +import androidx.test.ext.junit.runners.AndroidJUnit4; import androidx.test.filters.SmallTest; import androidx.test.rule.ServiceTestRule; -import androidx.test.runner.AndroidJUnit4; import org.junit.After; import org.junit.Before; diff --git a/core/tests/coretests/src/android/service/settings/suggestions/SuggestionTest.java b/core/tests/coretests/src/android/service/settings/suggestions/SuggestionTest.java index e0eb197f437a..03096de4b0d5 100644 --- a/core/tests/coretests/src/android/service/settings/suggestions/SuggestionTest.java +++ b/core/tests/coretests/src/android/service/settings/suggestions/SuggestionTest.java @@ -26,8 +26,8 @@ import android.graphics.drawable.Icon; import android.os.Parcel; import androidx.test.InstrumentationRegistry; +import androidx.test.ext.junit.runners.AndroidJUnit4; import androidx.test.filters.SmallTest; -import androidx.test.runner.AndroidJUnit4; import org.junit.Before; import org.junit.Test; diff --git a/core/tests/coretests/src/android/telephony/PinResultTest.java b/core/tests/coretests/src/android/telephony/PinResultTest.java index c260807e5cbc..f5432ee2da18 100644 --- a/core/tests/coretests/src/android/telephony/PinResultTest.java +++ b/core/tests/coretests/src/android/telephony/PinResultTest.java @@ -18,7 +18,7 @@ package android.telephony; import static com.google.common.truth.Truth.assertThat; -import androidx.test.runner.AndroidJUnit4; +import androidx.test.ext.junit.runners.AndroidJUnit4; import org.junit.Test; import org.junit.runner.RunWith; diff --git a/core/tests/coretests/src/android/text/BidiFormatterTest.java b/core/tests/coretests/src/android/text/BidiFormatterTest.java index 312fb68bbfc2..307c95b08bbb 100644 --- a/core/tests/coretests/src/android/text/BidiFormatterTest.java +++ b/core/tests/coretests/src/android/text/BidiFormatterTest.java @@ -20,8 +20,8 @@ import static org.junit.Assert.assertEquals; import android.platform.test.annotations.Presubmit; +import androidx.test.ext.junit.runners.AndroidJUnit4; import androidx.test.filters.SmallTest; -import androidx.test.runner.AndroidJUnit4; import org.junit.Test; import org.junit.runner.RunWith; diff --git a/core/tests/coretests/src/android/text/DynamicLayoutBlocksTest.java b/core/tests/coretests/src/android/text/DynamicLayoutBlocksTest.java index cca1ad3a6dec..81c498202b34 100644 --- a/core/tests/coretests/src/android/text/DynamicLayoutBlocksTest.java +++ b/core/tests/coretests/src/android/text/DynamicLayoutBlocksTest.java @@ -23,8 +23,8 @@ import static org.junit.Assert.assertTrue; import android.platform.test.annotations.Presubmit; +import androidx.test.ext.junit.runners.AndroidJUnit4; import androidx.test.filters.SmallTest; -import androidx.test.runner.AndroidJUnit4; import org.junit.Test; import org.junit.runner.RunWith; diff --git a/core/tests/coretests/src/android/text/DynamicLayoutOffsetMappingTest.java b/core/tests/coretests/src/android/text/DynamicLayoutOffsetMappingTest.java index 5939c0609e18..8a41678aa5f2 100644 --- a/core/tests/coretests/src/android/text/DynamicLayoutOffsetMappingTest.java +++ b/core/tests/coretests/src/android/text/DynamicLayoutOffsetMappingTest.java @@ -21,11 +21,18 @@ import static android.text.Layout.Alignment.ALIGN_NORMAL; import static com.google.common.truth.Truth.assertThat; import android.platform.test.annotations.Presubmit; +import android.platform.test.annotations.RequiresFlagsEnabled; +import android.platform.test.flag.junit.CheckFlagsRule; +import android.platform.test.flag.junit.DeviceFlagsValueProvider; import android.text.method.OffsetMapping; +import android.text.style.UpdateLayout; +import androidx.test.ext.junit.runners.AndroidJUnit4; import androidx.test.filters.SmallTest; -import androidx.test.runner.AndroidJUnit4; +import com.android.text.flags.Flags; + +import org.junit.Rule; import org.junit.Test; import org.junit.runner.RunWith; @@ -36,6 +43,9 @@ public class DynamicLayoutOffsetMappingTest { private static final int WIDTH = 10000; private static final TextPaint sTextPaint = new TextPaint(); + @Rule + public CheckFlagsRule mCheckFlagsRule = DeviceFlagsValueProvider.createCheckFlagsRule(); + @Test public void textWithOffsetMapping() { final String text = "abcde"; @@ -120,6 +130,84 @@ public class DynamicLayoutOffsetMappingTest { } @Test + @RequiresFlagsEnabled(Flags.FLAG_INSERT_MODE_CRASH_UPDATE_LAYOUT_SPAN) + public void textWithOffsetMapping_deletion_withUpdateLayoutSpan() { + final String text = "abcdef"; + final SpannableStringBuilder spannable = new SpannableStringBuilder(text); + // UpdateLayout span covers the letter 'd'. + spannable.setSpan(new UpdateLayout() {}, 3, 4, Spanned.SPAN_INCLUSIVE_EXCLUSIVE); + + final CharSequence transformedText = + new TestOffsetMapping(spannable, 3, "\n\n"); + + final DynamicLayout layout = DynamicLayout.Builder.obtain(spannable, sTextPaint, WIDTH) + .setAlignment(ALIGN_NORMAL) + .setIncludePad(false) + .setDisplayText(transformedText) + .build(); + + // delete character 'c', original text becomes "abdef" + spannable.delete(2, 3); + assertThat(transformedText.toString()).isEqualTo("ab\n\ndef"); + assertLineRange(layout, /* lineBreaks */ 0, 3, 4, 7); + + // delete character 'd', original text becomes "abef" + spannable.delete(2, 3); + assertThat(transformedText.toString()).isEqualTo("ab\n\nef"); + assertLineRange(layout, /* lineBreaks */ 0, 3, 4, 6); + + // delete "be", original text becomes "af" + spannable.delete(1, 3); + assertThat(transformedText.toString()).isEqualTo("a\n\nf"); + assertLineRange(layout, /* lineBreaks */ 0, 2, 3, 4); + } + + @Test + @RequiresFlagsEnabled(Flags.FLAG_INSERT_MODE_CRASH_UPDATE_LAYOUT_SPAN) + public void textWithOffsetMapping_insert_withUpdateLayoutSpan() { + final String text = "abcdef"; + final SpannableStringBuilder spannable = new SpannableStringBuilder(text); + final CharSequence transformedText = new TestOffsetMapping(spannable, 3, "\n\n"); + + // UpdateLayout span covers the letter 'de'. + spannable.setSpan(new UpdateLayout() {}, 3, 5, Spanned.SPAN_INCLUSIVE_EXCLUSIVE); + + final DynamicLayout layout = DynamicLayout.Builder.obtain(spannable, sTextPaint, WIDTH) + .setAlignment(ALIGN_NORMAL) + .setIncludePad(false) + .setDisplayText(transformedText) + .build(); + + spannable.insert(3, "x"); + assertThat(transformedText.toString()).isEqualTo("abcx\n\ndef"); + assertLineRange(layout, /* lineBreaks */ 0, 5, 6, 9); + + spannable.insert(5, "x"); + assertThat(transformedText.toString()).isEqualTo("abcx\n\ndxef"); + assertLineRange(layout, /* lineBreaks */ 0, 5, 6, 10); + } + + @Test + @RequiresFlagsEnabled(Flags.FLAG_INSERT_MODE_CRASH_UPDATE_LAYOUT_SPAN) + public void textWithOffsetMapping_replace_withUpdateLayoutSpan() { + final String text = "abcdef"; + final SpannableStringBuilder spannable = new SpannableStringBuilder(text); + final CharSequence transformedText = new TestOffsetMapping(spannable, 3, "\n\n"); + // UpdateLayout span covers the letter 'de'. + spannable.setSpan(new UpdateLayout() {}, 3, 5, Spanned.SPAN_INCLUSIVE_EXCLUSIVE); + + final DynamicLayout layout = DynamicLayout.Builder.obtain(spannable, sTextPaint, WIDTH) + .setAlignment(ALIGN_NORMAL) + .setIncludePad(false) + .setDisplayText(transformedText) + .build(); + + spannable.replace(2, 4, "xx"); + assertThat(transformedText.toString()).isEqualTo("abxx\n\nef"); + assertLineRange(layout, /* lineBreaks */ 0, 5, 6, 8); + } + + @Test public void textWithOffsetMapping_blockBeforeTextChanged_deletion() { final String text = "abcdef"; final SpannableStringBuilder spannable = new TestNoBeforeTextChangeSpannableString(text); diff --git a/core/tests/coretests/src/android/text/DynamicLayoutTest.java b/core/tests/coretests/src/android/text/DynamicLayoutTest.java index 699243b3f2b9..1036928b65d4 100644 --- a/core/tests/coretests/src/android/text/DynamicLayoutTest.java +++ b/core/tests/coretests/src/android/text/DynamicLayoutTest.java @@ -30,8 +30,8 @@ import android.platform.test.annotations.Presubmit; import android.text.style.ReplacementSpan; import android.util.ArraySet; +import androidx.test.ext.junit.runners.AndroidJUnit4; import androidx.test.filters.SmallTest; -import androidx.test.runner.AndroidJUnit4; import org.junit.Test; import org.junit.runner.RunWith; diff --git a/core/tests/coretests/src/android/text/EmojiConsistencyTest.java b/core/tests/coretests/src/android/text/EmojiConsistencyTest.java index c6e9e9cce829..72d09c8cbf33 100644 --- a/core/tests/coretests/src/android/text/EmojiConsistencyTest.java +++ b/core/tests/coretests/src/android/text/EmojiConsistencyTest.java @@ -18,8 +18,8 @@ package android.text; import static junit.framework.Assert.assertEquals; +import androidx.test.ext.junit.runners.AndroidJUnit4; import androidx.test.filters.SmallTest; -import androidx.test.runner.AndroidJUnit4; import org.junit.Test; import org.junit.runner.RunWith; diff --git a/core/tests/coretests/src/android/text/EmojiTest.java b/core/tests/coretests/src/android/text/EmojiTest.java index 0aeeb74df466..21f346e370a2 100644 --- a/core/tests/coretests/src/android/text/EmojiTest.java +++ b/core/tests/coretests/src/android/text/EmojiTest.java @@ -22,8 +22,8 @@ import static org.junit.Assert.assertTrue; import android.icu.lang.UCharacterDirection; import android.icu.text.Bidi; +import androidx.test.ext.junit.runners.AndroidJUnit4; import androidx.test.filters.SmallTest; -import androidx.test.runner.AndroidJUnit4; import org.junit.Test; import org.junit.runner.RunWith; diff --git a/core/tests/coretests/src/android/text/LayoutBidiCursorPathTest.java b/core/tests/coretests/src/android/text/LayoutBidiCursorPathTest.java index 96e7fb9c8b16..7728866e061c 100644 --- a/core/tests/coretests/src/android/text/LayoutBidiCursorPathTest.java +++ b/core/tests/coretests/src/android/text/LayoutBidiCursorPathTest.java @@ -26,8 +26,8 @@ import android.text.method.MetaKeyKeyListener; import android.view.KeyEvent; import androidx.test.InstrumentationRegistry; +import androidx.test.ext.junit.runners.AndroidJUnit4; import androidx.test.filters.SmallTest; -import androidx.test.runner.AndroidJUnit4; import org.junit.Before; import org.junit.Test; diff --git a/core/tests/coretests/src/android/text/LayoutTest.java b/core/tests/coretests/src/android/text/LayoutTest.java index 98f8b7fc897c..25f9cb7c1088 100644 --- a/core/tests/coretests/src/android/text/LayoutTest.java +++ b/core/tests/coretests/src/android/text/LayoutTest.java @@ -42,8 +42,8 @@ import android.text.Layout.Alignment; import android.text.style.ForegroundColorSpan; import android.text.style.StrikethroughSpan; +import androidx.test.ext.junit.runners.AndroidJUnit4; import androidx.test.filters.SmallTest; -import androidx.test.runner.AndroidJUnit4; import com.google.common.truth.Expect; diff --git a/core/tests/coretests/src/android/text/MeasuredParagraphTest.java b/core/tests/coretests/src/android/text/MeasuredParagraphTest.java index 02b67e25124a..921a6bd84191 100644 --- a/core/tests/coretests/src/android/text/MeasuredParagraphTest.java +++ b/core/tests/coretests/src/android/text/MeasuredParagraphTest.java @@ -26,8 +26,8 @@ import android.graphics.Typeface; import android.graphics.text.MeasuredText; import androidx.test.InstrumentationRegistry; +import androidx.test.ext.junit.runners.AndroidJUnit4; import androidx.test.filters.SmallTest; -import androidx.test.runner.AndroidJUnit4; import org.junit.Test; import org.junit.runner.RunWith; diff --git a/core/tests/coretests/src/android/text/PackedIntVectorTest.java b/core/tests/coretests/src/android/text/PackedIntVectorTest.java index ba15b92012a7..e8d706defbd4 100644 --- a/core/tests/coretests/src/android/text/PackedIntVectorTest.java +++ b/core/tests/coretests/src/android/text/PackedIntVectorTest.java @@ -20,8 +20,8 @@ import static org.junit.Assert.assertEquals; import android.platform.test.annotations.Presubmit; +import androidx.test.ext.junit.runners.AndroidJUnit4; import androidx.test.filters.SmallTest; -import androidx.test.runner.AndroidJUnit4; import org.junit.Test; import org.junit.runner.RunWith; diff --git a/core/tests/coretests/src/android/text/SpanColorsTest.java b/core/tests/coretests/src/android/text/SpanColorsTest.java index 3d8d8f9c126d..d2cb8c160d21 100644 --- a/core/tests/coretests/src/android/text/SpanColorsTest.java +++ b/core/tests/coretests/src/android/text/SpanColorsTest.java @@ -25,8 +25,8 @@ import android.text.style.ForegroundColorSpan; import android.text.style.ImageSpan; import android.text.style.UnderlineSpan; +import androidx.test.ext.junit.runners.AndroidJUnit4; import androidx.test.filters.SmallTest; -import androidx.test.runner.AndroidJUnit4; import org.junit.Before; import org.junit.Test; diff --git a/core/tests/coretests/src/android/text/SpannableStringBuilderTest.java b/core/tests/coretests/src/android/text/SpannableStringBuilderTest.java index 91b8c6ad0c53..b7251332683d 100644 --- a/core/tests/coretests/src/android/text/SpannableStringBuilderTest.java +++ b/core/tests/coretests/src/android/text/SpannableStringBuilderTest.java @@ -25,8 +25,8 @@ import android.text.style.QuoteSpan; import android.text.style.SubscriptSpan; import android.text.style.UnderlineSpan; +import androidx.test.ext.junit.runners.AndroidJUnit4; import androidx.test.filters.SmallTest; -import androidx.test.runner.AndroidJUnit4; import org.junit.Test; import org.junit.runner.RunWith; diff --git a/core/tests/coretests/src/android/text/SpannableStringNoCopyTest.java b/core/tests/coretests/src/android/text/SpannableStringNoCopyTest.java index 9149f7b1b216..a2952f6e3ed1 100644 --- a/core/tests/coretests/src/android/text/SpannableStringNoCopyTest.java +++ b/core/tests/coretests/src/android/text/SpannableStringNoCopyTest.java @@ -24,8 +24,8 @@ import android.annotation.NonNull; import android.text.style.QuoteSpan; import android.text.style.UnderlineSpan; +import androidx.test.ext.junit.runners.AndroidJUnit4; import androidx.test.filters.SmallTest; -import androidx.test.runner.AndroidJUnit4; import org.junit.Test; import org.junit.runner.RunWith; diff --git a/core/tests/coretests/src/android/text/SpannableTest.java b/core/tests/coretests/src/android/text/SpannableTest.java index d248a1f69030..a3e6a7812324 100644 --- a/core/tests/coretests/src/android/text/SpannableTest.java +++ b/core/tests/coretests/src/android/text/SpannableTest.java @@ -21,8 +21,8 @@ import static org.junit.Assert.assertEquals; import android.platform.test.annotations.Presubmit; import android.test.MoreAsserts; +import androidx.test.ext.junit.runners.AndroidJUnit4; import androidx.test.filters.SmallTest; -import androidx.test.runner.AndroidJUnit4; import org.junit.Test; import org.junit.runner.RunWith; diff --git a/core/tests/coretests/src/android/text/SpannedStringNoCopyTest.java b/core/tests/coretests/src/android/text/SpannedStringNoCopyTest.java index ca4373361fa5..3e2516fe6b35 100644 --- a/core/tests/coretests/src/android/text/SpannedStringNoCopyTest.java +++ b/core/tests/coretests/src/android/text/SpannedStringNoCopyTest.java @@ -24,8 +24,8 @@ import android.annotation.NonNull; import android.text.style.QuoteSpan; import android.text.style.UnderlineSpan; +import androidx.test.ext.junit.runners.AndroidJUnit4; import androidx.test.filters.SmallTest; -import androidx.test.runner.AndroidJUnit4; import org.junit.Test; import org.junit.runner.RunWith; diff --git a/core/tests/coretests/src/android/text/SpannedTest.java b/core/tests/coretests/src/android/text/SpannedTest.java index 3ab075509373..e9a357ce19a2 100644 --- a/core/tests/coretests/src/android/text/SpannedTest.java +++ b/core/tests/coretests/src/android/text/SpannedTest.java @@ -26,8 +26,8 @@ import android.text.style.StyleSpan; import android.text.style.TextAppearanceSpan; import android.text.style.TypefaceSpan; +import androidx.test.ext.junit.runners.AndroidJUnit4; import androidx.test.filters.SmallTest; -import androidx.test.runner.AndroidJUnit4; import org.junit.Test; import org.junit.runner.RunWith; diff --git a/core/tests/coretests/src/android/text/StaticLayoutBidiTest.java b/core/tests/coretests/src/android/text/StaticLayoutBidiTest.java index 32370b3e6e05..3deda8c28317 100644 --- a/core/tests/coretests/src/android/text/StaticLayoutBidiTest.java +++ b/core/tests/coretests/src/android/text/StaticLayoutBidiTest.java @@ -21,8 +21,8 @@ import static org.junit.Assert.assertEquals; import android.platform.test.annotations.Presubmit; import android.util.Log; +import androidx.test.ext.junit.runners.AndroidJUnit4; import androidx.test.filters.SmallTest; -import androidx.test.runner.AndroidJUnit4; import org.junit.Test; import org.junit.runner.RunWith; diff --git a/core/tests/coretests/src/android/text/StaticLayoutDirectionsTest.java b/core/tests/coretests/src/android/text/StaticLayoutDirectionsTest.java index 4221ac208948..bc7efe49ab5a 100644 --- a/core/tests/coretests/src/android/text/StaticLayoutDirectionsTest.java +++ b/core/tests/coretests/src/android/text/StaticLayoutDirectionsTest.java @@ -22,8 +22,8 @@ import android.platform.test.annotations.Presubmit; import android.text.Layout.Directions; import android.text.StaticLayoutTest.LayoutBuilder; +import androidx.test.ext.junit.runners.AndroidJUnit4; import androidx.test.filters.SmallTest; -import androidx.test.runner.AndroidJUnit4; import org.junit.Test; import org.junit.runner.RunWith; diff --git a/core/tests/coretests/src/android/text/StaticLayoutTest.java b/core/tests/coretests/src/android/text/StaticLayoutTest.java index 0ebf03fab966..3541900dcacf 100644 --- a/core/tests/coretests/src/android/text/StaticLayoutTest.java +++ b/core/tests/coretests/src/android/text/StaticLayoutTest.java @@ -31,8 +31,8 @@ import android.text.method.EditorState; import android.text.style.LocaleSpan; import android.util.Log; +import androidx.test.ext.junit.runners.AndroidJUnit4; import androidx.test.filters.SmallTest; -import androidx.test.runner.AndroidJUnit4; import org.junit.Before; import org.junit.Test; diff --git a/core/tests/coretests/src/android/text/StaticLayoutTextMeasuringTest.java b/core/tests/coretests/src/android/text/StaticLayoutTextMeasuringTest.java index 0d42326d4bdb..b32e94a8483c 100644 --- a/core/tests/coretests/src/android/text/StaticLayoutTextMeasuringTest.java +++ b/core/tests/coretests/src/android/text/StaticLayoutTextMeasuringTest.java @@ -21,8 +21,8 @@ import static org.junit.Assert.assertTrue; import android.text.Layout.Alignment; +import androidx.test.ext.junit.runners.AndroidJUnit4; import androidx.test.filters.SmallTest; -import androidx.test.runner.AndroidJUnit4; import org.junit.Before; import org.junit.Test; diff --git a/core/tests/coretests/src/android/text/TextLayoutTest.java b/core/tests/coretests/src/android/text/TextLayoutTest.java index 15fbc9e59508..1584bc32d4ce 100644 --- a/core/tests/coretests/src/android/text/TextLayoutTest.java +++ b/core/tests/coretests/src/android/text/TextLayoutTest.java @@ -18,8 +18,8 @@ package android.text; import android.platform.test.annotations.Presubmit; +import androidx.test.ext.junit.runners.AndroidJUnit4; import androidx.test.filters.SmallTest; -import androidx.test.runner.AndroidJUnit4; import org.junit.Before; import org.junit.Test; diff --git a/core/tests/coretests/src/android/text/TextLineTest.java b/core/tests/coretests/src/android/text/TextLineTest.java index 8ae5669de55f..2997853ad142 100644 --- a/core/tests/coretests/src/android/text/TextLineTest.java +++ b/core/tests/coretests/src/android/text/TextLineTest.java @@ -30,10 +30,10 @@ import android.text.style.AbsoluteSizeSpan; import android.text.style.ReplacementSpan; import android.text.style.TabStopSpan; +import androidx.test.ext.junit.runners.AndroidJUnit4; import androidx.test.filters.SmallTest; import androidx.test.filters.Suppress; import androidx.test.platform.app.InstrumentationRegistry; -import androidx.test.runner.AndroidJUnit4; import org.junit.Test; import org.junit.runner.RunWith; diff --git a/core/tests/coretests/src/android/text/TextShaperTest.java b/core/tests/coretests/src/android/text/TextShaperTest.java index 77b14e6fa57f..84112ae0f178 100644 --- a/core/tests/coretests/src/android/text/TextShaperTest.java +++ b/core/tests/coretests/src/android/text/TextShaperTest.java @@ -21,8 +21,8 @@ import static com.google.common.truth.Truth.assertWithMessage; import android.graphics.fonts.Font; import android.graphics.fonts.FontFileUtil; +import androidx.test.ext.junit.runners.AndroidJUnit4; import androidx.test.filters.SmallTest; -import androidx.test.runner.AndroidJUnit4; import org.junit.Test; import org.junit.runner.RunWith; diff --git a/core/tests/coretests/src/android/text/TextUtilsTest.java b/core/tests/coretests/src/android/text/TextUtilsTest.java index c4bcfd4cf117..f552265cc507 100644 --- a/core/tests/coretests/src/android/text/TextUtilsTest.java +++ b/core/tests/coretests/src/android/text/TextUtilsTest.java @@ -34,9 +34,9 @@ import android.text.util.Rfc822Token; import android.text.util.Rfc822Tokenizer; import android.view.View; +import androidx.test.ext.junit.runners.AndroidJUnit4; import androidx.test.filters.LargeTest; import androidx.test.filters.SmallTest; -import androidx.test.runner.AndroidJUnit4; import com.google.android.collect.Lists; diff --git a/core/tests/coretests/src/android/text/VariationParserTest.java b/core/tests/coretests/src/android/text/VariationParserTest.java index 0afe811f1ad6..8e93dd4a8dd3 100644 --- a/core/tests/coretests/src/android/text/VariationParserTest.java +++ b/core/tests/coretests/src/android/text/VariationParserTest.java @@ -22,8 +22,8 @@ import static org.junit.Assert.fail; import android.graphics.fonts.FontVariationAxis; import android.platform.test.annotations.Presubmit; +import androidx.test.ext.junit.runners.AndroidJUnit4; import androidx.test.filters.SmallTest; -import androidx.test.runner.AndroidJUnit4; import org.junit.Test; import org.junit.runner.RunWith; diff --git a/core/tests/coretests/src/android/text/format/DateFormatTest.java b/core/tests/coretests/src/android/text/format/DateFormatTest.java index 212cc44eefab..59af6dd20478 100644 --- a/core/tests/coretests/src/android/text/format/DateFormatTest.java +++ b/core/tests/coretests/src/android/text/format/DateFormatTest.java @@ -25,8 +25,8 @@ import android.compat.testing.PlatformCompatChangeRule; import android.icu.text.DateFormatSymbols; import android.platform.test.annotations.Presubmit; +import androidx.test.ext.junit.runners.AndroidJUnit4; import androidx.test.filters.SmallTest; -import androidx.test.runner.AndroidJUnit4; import libcore.junit.util.compat.CoreCompatChangeRule.DisableCompatChanges; import libcore.junit.util.compat.CoreCompatChangeRule.EnableCompatChanges; diff --git a/core/tests/coretests/src/android/text/format/DateIntervalFormatTest.java b/core/tests/coretests/src/android/text/format/DateIntervalFormatTest.java index 9750de386271..a07d399218e3 100644 --- a/core/tests/coretests/src/android/text/format/DateIntervalFormatTest.java +++ b/core/tests/coretests/src/android/text/format/DateIntervalFormatTest.java @@ -42,8 +42,8 @@ import android.icu.util.TimeZone; import android.icu.util.ULocale; import android.platform.test.annotations.Presubmit; +import androidx.test.ext.junit.runners.AndroidJUnit4; import androidx.test.filters.SmallTest; -import androidx.test.runner.AndroidJUnit4; import org.junit.Test; import org.junit.runner.RunWith; diff --git a/core/tests/coretests/src/android/text/format/DateUtilsTest.java b/core/tests/coretests/src/android/text/format/DateUtilsTest.java index 381c0512c532..47be893eb3e9 100644 --- a/core/tests/coretests/src/android/text/format/DateUtilsTest.java +++ b/core/tests/coretests/src/android/text/format/DateUtilsTest.java @@ -23,8 +23,8 @@ import android.content.res.Resources; import android.os.LocaleList; import android.platform.test.annotations.Presubmit; +import androidx.test.ext.junit.runners.AndroidJUnit4; import androidx.test.filters.SmallTest; -import androidx.test.runner.AndroidJUnit4; import org.junit.After; import org.junit.Before; diff --git a/core/tests/coretests/src/android/text/format/FormatterTest.java b/core/tests/coretests/src/android/text/format/FormatterTest.java index 986cee55a108..555292e83025 100644 --- a/core/tests/coretests/src/android/text/format/FormatterTest.java +++ b/core/tests/coretests/src/android/text/format/FormatterTest.java @@ -28,8 +28,8 @@ import android.platform.test.annotations.Presubmit; import android.text.format.Formatter.BytesResult; import androidx.test.InstrumentationRegistry; +import androidx.test.ext.junit.runners.AndroidJUnit4; import androidx.test.filters.SmallTest; -import androidx.test.runner.AndroidJUnit4; import org.junit.After; import org.junit.Before; diff --git a/core/tests/coretests/src/android/text/format/RelativeDateTimeFormatterTest.java b/core/tests/coretests/src/android/text/format/RelativeDateTimeFormatterTest.java index 2337802db71f..cd31950302cb 100644 --- a/core/tests/coretests/src/android/text/format/RelativeDateTimeFormatterTest.java +++ b/core/tests/coretests/src/android/text/format/RelativeDateTimeFormatterTest.java @@ -36,8 +36,8 @@ import static org.junit.Assert.fail; import android.platform.test.annotations.Presubmit; +import androidx.test.ext.junit.runners.AndroidJUnit4; import androidx.test.filters.SmallTest; -import androidx.test.runner.AndroidJUnit4; import org.junit.Test; import org.junit.runner.RunWith; diff --git a/core/tests/coretests/src/android/text/format/TimeMigrationUtilsTest.java b/core/tests/coretests/src/android/text/format/TimeMigrationUtilsTest.java index b605520c659d..c8cb5f38b185 100644 --- a/core/tests/coretests/src/android/text/format/TimeMigrationUtilsTest.java +++ b/core/tests/coretests/src/android/text/format/TimeMigrationUtilsTest.java @@ -20,8 +20,8 @@ import static org.junit.Assert.assertEquals; import android.platform.test.annotations.Presubmit; +import androidx.test.ext.junit.runners.AndroidJUnit4; import androidx.test.filters.SmallTest; -import androidx.test.runner.AndroidJUnit4; import org.junit.After; import org.junit.Before; diff --git a/core/tests/coretests/src/android/text/format/TimeTest.java b/core/tests/coretests/src/android/text/format/TimeTest.java index ac0041119640..6138ea1926dd 100644 --- a/core/tests/coretests/src/android/text/format/TimeTest.java +++ b/core/tests/coretests/src/android/text/format/TimeTest.java @@ -24,9 +24,9 @@ import android.platform.test.annotations.Presubmit; import android.util.Log; import android.util.TimeFormatException; +import androidx.test.ext.junit.runners.AndroidJUnit4; import androidx.test.filters.SmallTest; import androidx.test.filters.Suppress; -import androidx.test.runner.AndroidJUnit4; import org.junit.Test; import org.junit.runner.RunWith; diff --git a/core/tests/coretests/src/android/text/method/BackspaceTest.java b/core/tests/coretests/src/android/text/method/BackspaceTest.java index 19c2c6153558..a7ff244507cb 100644 --- a/core/tests/coretests/src/android/text/method/BackspaceTest.java +++ b/core/tests/coretests/src/android/text/method/BackspaceTest.java @@ -24,8 +24,8 @@ import android.widget.EditText; import android.widget.TextView.BufferType; import androidx.test.InstrumentationRegistry; +import androidx.test.ext.junit.runners.AndroidJUnit4; import androidx.test.filters.SmallTest; -import androidx.test.runner.AndroidJUnit4; import org.junit.Before; import org.junit.Test; diff --git a/core/tests/coretests/src/android/text/method/ForwardDeleteTest.java b/core/tests/coretests/src/android/text/method/ForwardDeleteTest.java index 652622db66c2..1e4024d92f97 100644 --- a/core/tests/coretests/src/android/text/method/ForwardDeleteTest.java +++ b/core/tests/coretests/src/android/text/method/ForwardDeleteTest.java @@ -24,8 +24,8 @@ import android.widget.EditText; import android.widget.TextView.BufferType; import androidx.test.InstrumentationRegistry; +import androidx.test.ext.junit.runners.AndroidJUnit4; import androidx.test.filters.SmallTest; -import androidx.test.runner.AndroidJUnit4; import org.junit.Before; import org.junit.Test; diff --git a/core/tests/coretests/src/android/text/method/InsertModeTransformationMethodTest.java b/core/tests/coretests/src/android/text/method/InsertModeTransformationMethodTest.java index 9ef137beebb2..2f336ab692f6 100644 --- a/core/tests/coretests/src/android/text/method/InsertModeTransformationMethodTest.java +++ b/core/tests/coretests/src/android/text/method/InsertModeTransformationMethodTest.java @@ -27,9 +27,8 @@ import android.text.style.ReplacementSpan; import android.view.View; import androidx.test.InstrumentationRegistry; +import androidx.test.ext.junit.runners.AndroidJUnit4; import androidx.test.filters.SmallTest; -import androidx.test.runner.AndroidJUnit4; - import org.junit.BeforeClass; import org.junit.Test; diff --git a/core/tests/coretests/src/android/text/method/WordIteratorTest.java b/core/tests/coretests/src/android/text/method/WordIteratorTest.java index cc345f5785df..046496aa1c99 100644 --- a/core/tests/coretests/src/android/text/method/WordIteratorTest.java +++ b/core/tests/coretests/src/android/text/method/WordIteratorTest.java @@ -23,8 +23,8 @@ import static org.junit.Assert.fail; import android.platform.test.annotations.Presubmit; +import androidx.test.ext.junit.runners.AndroidJUnit4; import androidx.test.filters.SmallTest; -import androidx.test.runner.AndroidJUnit4; import org.junit.Test; import org.junit.runner.RunWith; diff --git a/core/tests/coretests/src/android/text/style/UnderlineSpanTest.java b/core/tests/coretests/src/android/text/style/UnderlineSpanTest.java index a0d2f856d093..043960d07cd5 100644 --- a/core/tests/coretests/src/android/text/style/UnderlineSpanTest.java +++ b/core/tests/coretests/src/android/text/style/UnderlineSpanTest.java @@ -24,8 +24,8 @@ import android.text.Spanned; import android.text.StaticLayout; import android.text.TextPaint; +import androidx.test.ext.junit.runners.AndroidJUnit4; import androidx.test.filters.SmallTest; -import androidx.test.runner.AndroidJUnit4; import org.junit.Test; import org.junit.runner.RunWith; diff --git a/core/tests/coretests/src/android/text/util/LinkifyTest.java b/core/tests/coretests/src/android/text/util/LinkifyTest.java index 107ecd716b5a..52f3b2e0534f 100644 --- a/core/tests/coretests/src/android/text/util/LinkifyTest.java +++ b/core/tests/coretests/src/android/text/util/LinkifyTest.java @@ -31,8 +31,8 @@ import android.util.Patterns; import android.widget.TextView; import androidx.test.InstrumentationRegistry; +import androidx.test.ext.junit.runners.AndroidJUnit4; import androidx.test.filters.SmallTest; -import androidx.test.runner.AndroidJUnit4; import org.junit.After; import org.junit.Before; diff --git a/core/tests/coretests/src/android/tracing/perfetto/DataSourceTest.java b/core/tests/coretests/src/android/tracing/perfetto/DataSourceTest.java index df9a89e07404..bbeb18dfbecd 100644 --- a/core/tests/coretests/src/android/tracing/perfetto/DataSourceTest.java +++ b/core/tests/coretests/src/android/tracing/perfetto/DataSourceTest.java @@ -37,7 +37,7 @@ import android.tools.traces.monitors.TraceMonitor; import android.util.proto.ProtoInputStream; import android.util.proto.ProtoOutputStream; -import androidx.test.runner.AndroidJUnit4; +import androidx.test.ext.junit.runners.AndroidJUnit4; import com.google.common.truth.Truth; import com.google.protobuf.InvalidProtocolBufferException; diff --git a/core/tests/coretests/src/android/transition/AutoTransitionTest.java b/core/tests/coretests/src/android/transition/AutoTransitionTest.java index deae967a3e72..5d58feadc25b 100644 --- a/core/tests/coretests/src/android/transition/AutoTransitionTest.java +++ b/core/tests/coretests/src/android/transition/AutoTransitionTest.java @@ -20,8 +20,8 @@ import static org.junit.Assert.assertEquals; import static org.junit.Assert.assertNotNull; import static org.junit.Assert.assertTrue; +import androidx.test.ext.junit.runners.AndroidJUnit4; import androidx.test.filters.SmallTest; -import androidx.test.runner.AndroidJUnit4; import org.junit.Test; import org.junit.runner.RunWith; diff --git a/core/tests/coretests/src/android/view/ViewFrameRateTest.java b/core/tests/coretests/src/android/view/ViewFrameRateTest.java index 18364ad5e2b6..b8ff59528b24 100644 --- a/core/tests/coretests/src/android/view/ViewFrameRateTest.java +++ b/core/tests/coretests/src/android/view/ViewFrameRateTest.java @@ -278,7 +278,7 @@ public class ViewFrameRateTest { @RequiresFlagsEnabled({FLAG_VIEW_VELOCITY_API, FLAG_TOOLKIT_FRAME_RATE_VELOCITY_MAPPING_READ_ONLY, FLAG_TOOLKIT_FRAME_RATE_VIEW_ENABLING_READ_ONLY}) - public void lowVelocity80() throws Throwable { + public void lowVelocity60() throws Throwable { if (!ViewProperties.vrr_enabled().orElse(true)) { return; } @@ -292,6 +292,31 @@ public class ViewFrameRateTest { mActivityRule.runOnUiThread(() -> { mMovingView.setFrameContentVelocity(1f); mMovingView.invalidate(); + runAfterDraw(() -> assertEquals(60f, mViewRoot.getLastPreferredFrameRate(), 0f)); + }); + waitForAfterDraw(); + } + + @Test + @RequiresFlagsEnabled({FLAG_VIEW_VELOCITY_API, + FLAG_TOOLKIT_FRAME_RATE_VELOCITY_MAPPING_READ_ONLY, + FLAG_TOOLKIT_FRAME_RATE_VIEW_ENABLING_READ_ONLY}) + public void midVelocity80() throws Throwable { + if (!ViewProperties.vrr_enabled().orElse(true)) { + return; + } + mActivityRule.runOnUiThread(() -> { + ViewGroup.LayoutParams layoutParams = mMovingView.getLayoutParams(); + layoutParams.width = ViewGroup.LayoutParams.MATCH_PARENT; + layoutParams.height = ViewGroup.LayoutParams.MATCH_PARENT; + mMovingView.setLayoutParams(layoutParams); + }); + waitForFrameRateCategoryToSettle(); + mActivityRule.runOnUiThread(() -> { + float midSpeed = + 200f * mMovingView.getContext().getResources().getDisplayMetrics().density; + mMovingView.setFrameContentVelocity(midSpeed); + mMovingView.invalidate(); runAfterDraw(() -> assertEquals(80f, mViewRoot.getLastPreferredFrameRate(), 0f)); }); waitForAfterDraw(); @@ -321,7 +346,7 @@ public class ViewFrameRateTest { frameLayout.setFrameContentVelocity(1f); mMovingView.offsetTopAndBottom(100); frameLayout.invalidate(); - runAfterDraw(() -> assertEquals(80f, mViewRoot.getLastPreferredFrameRate(), 0f)); + runAfterDraw(() -> assertEquals(60f, mViewRoot.getLastPreferredFrameRate(), 0f)); }); waitForAfterDraw(); } @@ -590,7 +615,7 @@ public class ViewFrameRateTest { runAfterDraw(() -> { assertEquals(FRAME_RATE_CATEGORY_LOW, mViewRoot.getLastPreferredFrameRateCategory()); - assertEquals(80f, mViewRoot.getLastPreferredFrameRate()); + assertEquals(60f, mViewRoot.getLastPreferredFrameRate()); }); }); waitForAfterDraw(); diff --git a/core/tests/coretests/src/android/view/accessibility/AccessibilityCacheTest.java b/core/tests/coretests/src/android/view/accessibility/AccessibilityCacheTest.java index dd8cc6e0dd03..e5ad5613af2d 100644 --- a/core/tests/coretests/src/android/view/accessibility/AccessibilityCacheTest.java +++ b/core/tests/coretests/src/android/view/accessibility/AccessibilityCacheTest.java @@ -42,8 +42,8 @@ import android.util.SparseArray; import android.view.Display; import android.view.View; +import androidx.test.ext.junit.runners.AndroidJUnit4; import androidx.test.filters.LargeTest; -import androidx.test.runner.AndroidJUnit4; import com.google.common.base.Throwables; @@ -1053,6 +1053,28 @@ public class AccessibilityCacheTest { assertFalse(mAccessibilityCache.isNodeInCache(childInfo)); } + @Test + public void getEventSourceClassName_windowStateChangedThenRemoved() { + final String sourceActivityClassName = "com.example.SomeActivity"; + final AccessibilityEvent windowStateChangedEvent = new AccessibilityEvent( + AccessibilityEvent.TYPE_WINDOW_STATE_CHANGED); + final View mockView = getMockViewWithA11yAndWindowIds(PARENT_VIEW_ID, WINDOW_ID_1); + windowStateChangedEvent.setSource(mockView); + windowStateChangedEvent.setClassName(sourceActivityClassName); + + mAccessibilityCache.onAccessibilityEvent(windowStateChangedEvent); + assertEquals(mAccessibilityCache.getEventSourceClassName(WINDOW_ID_1), + sourceActivityClassName); + + final AccessibilityEvent windowRemovedEvent = new AccessibilityEvent( + AccessibilityEvent.TYPE_WINDOWS_CHANGED); + windowRemovedEvent.setWindowChanges(AccessibilityEvent.WINDOWS_CHANGE_REMOVED); + windowRemovedEvent.setSource(mockView); + + mAccessibilityCache.onAccessibilityEvent(windowRemovedEvent); + assertNull(mAccessibilityCache.getEventSourceClassName(WINDOW_ID_1)); + } + private AccessibilityWindowInfo obtainAccessibilityWindowInfo(int windowId, int layer) { AccessibilityWindowInfo windowInfo = AccessibilityWindowInfo.obtain(); windowInfo.setId(windowId); diff --git a/core/tests/coretests/src/android/view/accessibility/AccessibilityEventTest.java b/core/tests/coretests/src/android/view/accessibility/AccessibilityEventTest.java index ddc27aacc86f..3b8f66aba063 100644 --- a/core/tests/coretests/src/android/view/accessibility/AccessibilityEventTest.java +++ b/core/tests/coretests/src/android/view/accessibility/AccessibilityEventTest.java @@ -23,7 +23,7 @@ import static junit.framework.Assert.assertTrue; import android.os.Parcel; import android.view.Display; -import androidx.test.runner.AndroidJUnit4; +import androidx.test.ext.junit.runners.AndroidJUnit4; import org.junit.Test; import org.junit.runner.RunWith; diff --git a/core/tests/coretests/src/android/view/accessibility/AccessibilityInteractionClientTest.java b/core/tests/coretests/src/android/view/accessibility/AccessibilityInteractionClientTest.java index 3e061d208937..eb482f2e0aa5 100644 --- a/core/tests/coretests/src/android/view/accessibility/AccessibilityInteractionClientTest.java +++ b/core/tests/coretests/src/android/view/accessibility/AccessibilityInteractionClientTest.java @@ -26,8 +26,8 @@ import static org.mockito.MockitoAnnotations.initMocks; import android.os.Bundle; import android.os.RemoteException; +import androidx.test.ext.junit.runners.AndroidJUnit4; import androidx.test.filters.LargeTest; -import androidx.test.runner.AndroidJUnit4; import libcore.util.EmptyArray; diff --git a/core/tests/coretests/src/android/view/accessibility/AccessibilityManagerTest.java b/core/tests/coretests/src/android/view/accessibility/AccessibilityManagerTest.java index ce36ee06bb38..82e34275c66c 100644 --- a/core/tests/coretests/src/android/view/accessibility/AccessibilityManagerTest.java +++ b/core/tests/coretests/src/android/view/accessibility/AccessibilityManagerTest.java @@ -55,7 +55,7 @@ import android.view.Display; import androidx.annotation.NonNull; import androidx.test.InstrumentationRegistry; -import androidx.test.runner.AndroidJUnit4; +import androidx.test.ext.junit.runners.AndroidJUnit4; import com.android.internal.R; import com.android.internal.accessibility.common.ShortcutConstants; diff --git a/core/tests/coretests/src/android/view/accessibility/AccessibilityNodeInfoTest.java b/core/tests/coretests/src/android/view/accessibility/AccessibilityNodeInfoTest.java index 2d82d231e279..a5137bdf80b8 100644 --- a/core/tests/coretests/src/android/view/accessibility/AccessibilityNodeInfoTest.java +++ b/core/tests/coretests/src/android/view/accessibility/AccessibilityNodeInfoTest.java @@ -28,8 +28,8 @@ import android.os.Parcel; import android.util.ArraySet; import android.view.accessibility.AccessibilityNodeInfo.AccessibilityAction; +import androidx.test.ext.junit.runners.AndroidJUnit4; import androidx.test.filters.LargeTest; -import androidx.test.runner.AndroidJUnit4; import com.android.internal.util.CollectionUtils; @@ -46,7 +46,7 @@ public class AccessibilityNodeInfoTest { // The number of fields tested in the corresponding CTS AccessibilityNodeInfoTest: // See fullyPopulateAccessibilityNodeInfo, assertEqualsAccessibilityNodeInfo, // and assertAccessibilityNodeInfoCleared in that class. - private static final int NUM_MARSHALLED_PROPERTIES = 44; + private static final int NUM_MARSHALLED_PROPERTIES = 43; /** * The number of properties that are purposely not marshalled diff --git a/core/tests/coretests/src/android/view/autofill/AutofillStateFingerprintTest.java b/core/tests/coretests/src/android/view/autofill/AutofillStateFingerprintTest.java new file mode 100644 index 000000000000..7cbfc40a62f1 --- /dev/null +++ b/core/tests/coretests/src/android/view/autofill/AutofillStateFingerprintTest.java @@ -0,0 +1,155 @@ +/* + * Copyright (C) 2024 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package android.view.autofill; + +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertNotEquals; + +import android.content.Context; +import android.text.InputType; +import android.view.View; +import android.view.inputmethod.EditorInfo; +import android.widget.TextView; + +import androidx.test.core.app.ApplicationProvider; + +import org.junit.Test; +import org.junit.runner.RunWith; +import org.junit.runners.JUnit4; + +@RunWith(JUnit4.class) +public class AutofillStateFingerprintTest { + + private static final Context sContext = ApplicationProvider.getApplicationContext(); + + private static final int MAGIC_AUTOFILL_NUMBER = 1000; + + private AutofillStateFingerprint mAutofillStateFingerprint = + AutofillStateFingerprint.createInstance(); + + @Test + public void testSameFingerprintsForTextView() throws Exception { + TextView tv = new TextView(sContext); + tv.setHint("Password"); + tv.setSingleLine(true); + tv.setInputType(InputType.TYPE_TEXT_VARIATION_PASSWORD); + tv.setImeOptions(EditorInfo.IME_FLAG_NAVIGATE_NEXT); + fillViewProperties(tv); + + // Create a copy Text View, and compare both id's + View tvCopy = copySelectiveViewAttributes(tv); + assertIdsEqual(tv, tvCopy); + } + + @Test + public void testDifferentFingerprintsForTextViewWithDifferentHint() throws Exception { + TextView tv = new TextView(sContext); + tv.setHint("Password"); + tv.setSingleLine(true); + tv.setInputType(InputType.TYPE_TEXT_VARIATION_PASSWORD); + tv.setImeOptions(EditorInfo.IME_FLAG_NAVIGATE_NEXT); + fillViewProperties(tv); + + TextView tvCopy = (TextView) copySelectiveViewAttributes(tv); + tvCopy.setHint("what a useless different hint"); + assertIdsNotEqual(tv, tvCopy); + } + + @Test + public void testSameFingerprintsForNonTextView() throws Exception { + View v = new View(sContext); + fillViewProperties(v); + + // Create a copy Text View, and compare both id's + View copy = copySelectiveViewAttributes(v); + assertIdsEqual(v, copy); + } + + @Test + public void testDifferentFingerprintsForNonTextViewWithDifferentVisibility() throws Exception { + View v = new View(sContext); + fillViewProperties(v); + + View copy = copySelectiveViewAttributes(v); + copy.setVisibility(View.GONE); + assertIdsNotEqual(v, copy); + } + + private void assertIdsEqual(View v1, View v2) { + assertEquals(mAutofillStateFingerprint.getEphemeralFingerprintId(v1, 0), + mAutofillStateFingerprint.getEphemeralFingerprintId(v2, 0)); + } + + private void assertIdsNotEqual(View v1, View v2) { + assertNotEquals(mAutofillStateFingerprint.getEphemeralFingerprintId(v1, 0), + mAutofillStateFingerprint.getEphemeralFingerprintId(v2, 0)); + } + + private void fillViewProperties(View view) { + // Fill in relevant view properties + view.setContentDescription("ContentDesc"); + view.setTooltipText("TooltipText"); + view.setAutofillHints(new String[] {"password"}); + view.setVisibility(View.VISIBLE); + view.setLeft(20); + view.setRight(200); + view.setTop(20); + view.setBottom(200); + view.setPadding(0, 1, 2, 3); + } + + // Only copy interesting view attributes, particularly the view attributes that are critical + // for calculating fingerprint. Keep Autofill Id different. + private View copySelectiveViewAttributes(View view) { + View copy; + if (view instanceof TextView) { + copy = new TextView(sContext); + copySelectiveTextViewAttributes((TextView) view, (TextView) copy); + } else { + copy = new View(sContext) { + public @AutofillType int getAutofillType() { + return view.getAutofillType(); + } + }; + } + // Copy over interested view properties. + // Keep the order same as with the tested code for easier clarity. + copy.setVisibility(view.getVisibility()); + copy.setAutofillHints(view.getAutofillHints()); + copy.setContentDescription(view.getContentDescription()); + copy.setTooltip(view.getTooltipText()); + + copy.setRight(view.getRight()); + copy.setLeft(view.getLeft()); + copy.setTop(view.getTop()); + copy.setBottom(view.getBottom()); + copy.setPadding(view.getPaddingLeft(), view.getPaddingTop(), + view.getPaddingRight(), view.getPaddingBottom()); + + // DO not copy over autofill id + AutofillId newId = new AutofillId(view.getAutofillId().getViewId() + MAGIC_AUTOFILL_NUMBER); + copy.setAutofillId(newId); + return copy; + } + + private void copySelectiveTextViewAttributes(TextView fromView, TextView toView) { + toView.setInputType(fromView.getInputType()); + toView.setHint(fromView.getHint()); + toView.setSingleLine(fromView.isSingleLine()); + toView.setImeOptions(fromView.getImeOptions()); + } +} diff --git a/core/tests/coretests/src/com/android/internal/accessibility/AccessibilityShortcutChooserActivityTest.java b/core/tests/coretests/src/com/android/internal/accessibility/AccessibilityShortcutChooserActivityTest.java index 9f5ed294eca2..37625e213afe 100644 --- a/core/tests/coretests/src/com/android/internal/accessibility/AccessibilityShortcutChooserActivityTest.java +++ b/core/tests/coretests/src/com/android/internal/accessibility/AccessibilityShortcutChooserActivityTest.java @@ -67,8 +67,8 @@ import android.widget.Button; import androidx.lifecycle.Lifecycle; import androidx.test.core.app.ActivityScenario; +import androidx.test.ext.junit.runners.AndroidJUnit4; import androidx.test.platform.app.InstrumentationRegistry; -import androidx.test.runner.AndroidJUnit4; import com.android.internal.R; import com.android.internal.accessibility.dialog.AccessibilityShortcutChooserActivity; diff --git a/core/tests/coretests/src/com/android/internal/accessibility/dialog/AccessibilityTargetTest.java b/core/tests/coretests/src/com/android/internal/accessibility/dialog/AccessibilityTargetTest.java index f01ac6f6fa10..8608f6c8fff0 100644 --- a/core/tests/coretests/src/com/android/internal/accessibility/dialog/AccessibilityTargetTest.java +++ b/core/tests/coretests/src/com/android/internal/accessibility/dialog/AccessibilityTargetTest.java @@ -27,7 +27,7 @@ import android.platform.test.annotations.EnableFlags; import android.platform.test.flag.junit.SetFlagsRule; import android.provider.Flags; -import androidx.test.runner.AndroidJUnit4; +import androidx.test.ext.junit.runners.AndroidJUnit4; import com.android.internal.accessibility.common.ShortcutConstants; diff --git a/core/tests/coretests/src/com/android/internal/accessibility/dialog/InvisibleToggleAccessibilityServiceTargetTest.java b/core/tests/coretests/src/com/android/internal/accessibility/dialog/InvisibleToggleAccessibilityServiceTargetTest.java index 9cac3120d1d9..5339d915c8a4 100644 --- a/core/tests/coretests/src/com/android/internal/accessibility/dialog/InvisibleToggleAccessibilityServiceTargetTest.java +++ b/core/tests/coretests/src/com/android/internal/accessibility/dialog/InvisibleToggleAccessibilityServiceTargetTest.java @@ -41,8 +41,8 @@ import android.view.accessibility.AccessibilityManager; import android.view.accessibility.Flags; import android.view.accessibility.IAccessibilityManager; +import androidx.test.ext.junit.runners.AndroidJUnit4; import androidx.test.platform.app.InstrumentationRegistry; -import androidx.test.runner.AndroidJUnit4; import com.android.internal.accessibility.TestUtils; import com.android.internal.accessibility.common.ShortcutConstants; diff --git a/core/tests/coretests/src/com/android/internal/accessibility/util/AccessibilityUtilsTest.java b/core/tests/coretests/src/com/android/internal/accessibility/util/AccessibilityUtilsTest.java index 58ab92af7dbd..f37ec9bf7843 100644 --- a/core/tests/coretests/src/com/android/internal/accessibility/util/AccessibilityUtilsTest.java +++ b/core/tests/coretests/src/com/android/internal/accessibility/util/AccessibilityUtilsTest.java @@ -33,7 +33,7 @@ import android.text.ParcelableSpan; import android.text.SpannableString; import android.text.style.LocaleSpan; -import androidx.test.runner.AndroidJUnit4; +import androidx.test.ext.junit.runners.AndroidJUnit4; import org.junit.Before; import org.junit.Test; diff --git a/core/tests/coretests/src/com/android/internal/app/BilingualSuggestedLocaleAdapterTest.java b/core/tests/coretests/src/com/android/internal/app/BilingualSuggestedLocaleAdapterTest.java index e8aac113c312..d577e0fcd4bc 100644 --- a/core/tests/coretests/src/com/android/internal/app/BilingualSuggestedLocaleAdapterTest.java +++ b/core/tests/coretests/src/com/android/internal/app/BilingualSuggestedLocaleAdapterTest.java @@ -18,7 +18,7 @@ package com.android.internal.app; import static com.google.common.truth.Truth.assertThat; -import androidx.test.runner.AndroidJUnit4; +import androidx.test.ext.junit.runners.AndroidJUnit4; import com.android.internal.app.LocaleHelper.LocaleInfoComparator; import com.android.internal.app.LocaleStore.LocaleInfo; diff --git a/core/tests/coretests/src/com/android/internal/app/IntentForwarderActivityTest.java b/core/tests/coretests/src/com/android/internal/app/IntentForwarderActivityTest.java index dbabceaaf3cd..73a64fc688e0 100644 --- a/core/tests/coretests/src/com/android/internal/app/IntentForwarderActivityTest.java +++ b/core/tests/coretests/src/com/android/internal/app/IntentForwarderActivityTest.java @@ -57,8 +57,8 @@ import android.platform.test.flag.junit.SetFlagsRule; import android.provider.Settings; import androidx.test.InstrumentationRegistry; +import androidx.test.ext.junit.runners.AndroidJUnit4; import androidx.test.rule.ActivityTestRule; -import androidx.test.runner.AndroidJUnit4; import com.android.internal.R; import com.android.internal.logging.MetricsLogger; diff --git a/core/tests/coretests/src/com/android/internal/app/NoOpResolverComparatorTest.java b/core/tests/coretests/src/com/android/internal/app/NoOpResolverComparatorTest.java index 22c319cd4d08..0ed0a81c1234 100644 --- a/core/tests/coretests/src/com/android/internal/app/NoOpResolverComparatorTest.java +++ b/core/tests/coretests/src/com/android/internal/app/NoOpResolverComparatorTest.java @@ -22,7 +22,7 @@ import android.content.Intent; import android.os.UserHandle; import androidx.test.InstrumentationRegistry; -import androidx.test.runner.AndroidJUnit4; +import androidx.test.ext.junit.runners.AndroidJUnit4; import com.android.internal.app.ResolverActivity.ResolvedComponentInfo; diff --git a/core/tests/coretests/src/com/android/internal/app/ResolverActivityTest.java b/core/tests/coretests/src/com/android/internal/app/ResolverActivityTest.java index ff280555a3a1..d21ab44d251d 100644 --- a/core/tests/coretests/src/com/android/internal/app/ResolverActivityTest.java +++ b/core/tests/coretests/src/com/android/internal/app/ResolverActivityTest.java @@ -57,8 +57,8 @@ import android.widget.TextView; import androidx.test.InstrumentationRegistry; import androidx.test.espresso.Espresso; import androidx.test.espresso.NoMatchingViewException; +import androidx.test.ext.junit.runners.AndroidJUnit4; import androidx.test.rule.ActivityTestRule; -import androidx.test.runner.AndroidJUnit4; import com.android.internal.R; import com.android.internal.app.ResolverActivity.ResolvedComponentInfo; diff --git a/core/tests/coretests/src/com/android/internal/app/ResolverAppPredictorCallbackTest.java b/core/tests/coretests/src/com/android/internal/app/ResolverAppPredictorCallbackTest.java index 4aca854469f2..bde9bdb8c7c9 100644 --- a/core/tests/coretests/src/com/android/internal/app/ResolverAppPredictorCallbackTest.java +++ b/core/tests/coretests/src/com/android/internal/app/ResolverAppPredictorCallbackTest.java @@ -21,7 +21,7 @@ import android.app.prediction.AppTarget; import android.app.prediction.AppTargetId; import android.os.UserHandle; -import androidx.test.runner.AndroidJUnit4; +import androidx.test.ext.junit.runners.AndroidJUnit4; import org.junit.Test; import org.junit.runner.RunWith; diff --git a/core/tests/coretests/src/com/android/internal/app/ResolverListControllerTest.java b/core/tests/coretests/src/com/android/internal/app/ResolverListControllerTest.java index 8f6cee33078e..90f5c24e13a1 100644 --- a/core/tests/coretests/src/com/android/internal/app/ResolverListControllerTest.java +++ b/core/tests/coretests/src/com/android/internal/app/ResolverListControllerTest.java @@ -45,7 +45,7 @@ import android.os.UserHandle; import android.util.ArrayMap; import androidx.test.InstrumentationRegistry; -import androidx.test.runner.AndroidJUnit4; +import androidx.test.ext.junit.runners.AndroidJUnit4; import com.android.internal.app.ResolverActivity.ResolvedComponentInfo; diff --git a/core/tests/coretests/src/com/android/internal/infra/AndroidFutureTest.java b/core/tests/coretests/src/com/android/internal/infra/AndroidFutureTest.java index 3a272256e60e..178e93a6a37b 100644 --- a/core/tests/coretests/src/com/android/internal/infra/AndroidFutureTest.java +++ b/core/tests/coretests/src/com/android/internal/infra/AndroidFutureTest.java @@ -22,7 +22,7 @@ import static org.testng.Assert.expectThrows; import android.os.Parcel; -import androidx.test.runner.AndroidJUnit4; +import androidx.test.ext.junit.runners.AndroidJUnit4; import org.junit.Test; import org.junit.runner.RunWith; diff --git a/core/tests/coretests/src/com/android/internal/infra/ServiceConnectorTest.java b/core/tests/coretests/src/com/android/internal/infra/ServiceConnectorTest.java index 725dcf30d485..3d1b565cdc54 100644 --- a/core/tests/coretests/src/com/android/internal/infra/ServiceConnectorTest.java +++ b/core/tests/coretests/src/com/android/internal/infra/ServiceConnectorTest.java @@ -29,8 +29,8 @@ import android.os.Process; import android.os.UserHandle; import androidx.annotation.NonNull; +import androidx.test.ext.junit.runners.AndroidJUnit4; import androidx.test.platform.app.InstrumentationRegistry; -import androidx.test.runner.AndroidJUnit4; import com.android.frameworks.coretests.aidl.ITestServiceConnectorService; import com.android.internal.infra.ServiceConnectorTest.CapturingServiceLifecycleCallbacks.ServiceLifeCycleEvent; diff --git a/core/tests/coretests/src/com/android/internal/logging/MetricsLoggerTest.java b/core/tests/coretests/src/com/android/internal/logging/MetricsLoggerTest.java index 7054cc0f24b4..b86cb4ad2339 100644 --- a/core/tests/coretests/src/com/android/internal/logging/MetricsLoggerTest.java +++ b/core/tests/coretests/src/com/android/internal/logging/MetricsLoggerTest.java @@ -20,8 +20,8 @@ import static com.google.common.truth.Truth.assertThat; import android.metrics.LogMaker; +import androidx.test.ext.junit.runners.AndroidJUnit4; import androidx.test.filters.SmallTest; -import androidx.test.runner.AndroidJUnit4; import com.android.internal.logging.nano.MetricsProto; import com.android.internal.logging.testing.FakeMetricsLogger; diff --git a/core/tests/coretests/src/com/android/internal/logging/UiEventLoggerTest.java b/core/tests/coretests/src/com/android/internal/logging/UiEventLoggerTest.java index 7840f7177278..fc2862756d8b 100644 --- a/core/tests/coretests/src/com/android/internal/logging/UiEventLoggerTest.java +++ b/core/tests/coretests/src/com/android/internal/logging/UiEventLoggerTest.java @@ -18,8 +18,8 @@ package com.android.internal.logging; import static com.google.common.truth.Truth.assertThat; +import androidx.test.ext.junit.runners.AndroidJUnit4; import androidx.test.filters.SmallTest; -import androidx.test.runner.AndroidJUnit4; import com.android.internal.logging.testing.UiEventLoggerFake; diff --git a/core/tests/coretests/src/com/android/internal/policy/DecorContextTest.java b/core/tests/coretests/src/com/android/internal/policy/DecorContextTest.java index 7f4e9ada7b22..2f3b7f968a61 100644 --- a/core/tests/coretests/src/com/android/internal/policy/DecorContextTest.java +++ b/core/tests/coretests/src/com/android/internal/policy/DecorContextTest.java @@ -36,9 +36,9 @@ import android.view.WindowManager; import android.view.WindowManagerImpl; import androidx.test.core.app.ApplicationProvider; +import androidx.test.ext.junit.runners.AndroidJUnit4; import androidx.test.filters.SmallTest; import androidx.test.rule.ActivityTestRule; -import androidx.test.runner.AndroidJUnit4; import org.junit.Before; import org.junit.Rule; diff --git a/core/tests/coretests/src/com/android/internal/policy/PhoneWindowTest.java b/core/tests/coretests/src/com/android/internal/policy/PhoneWindowTest.java index 4921e4a4a061..e037f2acd16d 100644 --- a/core/tests/coretests/src/com/android/internal/policy/PhoneWindowTest.java +++ b/core/tests/coretests/src/com/android/internal/policy/PhoneWindowTest.java @@ -44,8 +44,8 @@ import android.view.ViewRootImpl; import android.view.WindowManager; import androidx.test.InstrumentationRegistry; +import androidx.test.ext.junit.runners.AndroidJUnit4; import androidx.test.filters.SmallTest; -import androidx.test.runner.AndroidJUnit4; import com.android.frameworks.coretests.R; diff --git a/core/tests/coretests/src/com/android/internal/ravenwood/RavenwoodEnvironmentTest.java b/core/tests/coretests/src/com/android/internal/ravenwood/RavenwoodEnvironmentTest.java index d1ef61b2e365..d1c066821cff 100644 --- a/core/tests/coretests/src/com/android/internal/ravenwood/RavenwoodEnvironmentTest.java +++ b/core/tests/coretests/src/com/android/internal/ravenwood/RavenwoodEnvironmentTest.java @@ -19,7 +19,7 @@ import static junit.framework.TestCase.assertEquals; import android.platform.test.ravenwood.RavenwoodRule; -import androidx.test.runner.AndroidJUnit4; +import androidx.test.ext.junit.runners.AndroidJUnit4; import org.junit.Rule; import org.junit.Test; diff --git a/libs/WindowManager/Jetpack/src/androidx/window/util/AcceptOnceConsumer.java b/libs/WindowManager/Jetpack/src/androidx/window/common/AcceptOnceConsumer.java index 63828ab2e62b..c2f827a22fc2 100644 --- a/libs/WindowManager/Jetpack/src/androidx/window/util/AcceptOnceConsumer.java +++ b/libs/WindowManager/Jetpack/src/androidx/window/common/AcceptOnceConsumer.java @@ -14,7 +14,7 @@ * limitations under the License. */ -package androidx.window.util; +package androidx.window.common; import android.annotation.NonNull; diff --git a/libs/WindowManager/Jetpack/src/androidx/window/util/BaseDataProducer.java b/libs/WindowManager/Jetpack/src/androidx/window/common/BaseDataProducer.java index cd26efd4fdb6..e7099dc3a281 100644 --- a/libs/WindowManager/Jetpack/src/androidx/window/util/BaseDataProducer.java +++ b/libs/WindowManager/Jetpack/src/androidx/window/common/BaseDataProducer.java @@ -14,7 +14,7 @@ * limitations under the License. */ -package androidx.window.util; +package androidx.window.common; import androidx.annotation.GuardedBy; import androidx.annotation.NonNull; @@ -125,4 +125,4 @@ public abstract class BaseDataProducer<T> implements mCallbacksToRemove.add(callback); } } -}
\ No newline at end of file +} diff --git a/libs/WindowManager/Jetpack/src/androidx/window/common/CommonFoldingFeature.java b/libs/WindowManager/Jetpack/src/androidx/window/common/CommonFoldingFeature.java index e37dea4dfd69..b95bca16ef5b 100644 --- a/libs/WindowManager/Jetpack/src/androidx/window/common/CommonFoldingFeature.java +++ b/libs/WindowManager/Jetpack/src/androidx/window/common/CommonFoldingFeature.java @@ -16,7 +16,7 @@ package androidx.window.common; -import static androidx.window.util.ExtensionHelper.isZero; +import static androidx.window.common.ExtensionHelper.isZero; import android.annotation.IntDef; import android.annotation.Nullable; diff --git a/libs/WindowManager/Jetpack/src/androidx/window/common/DeviceStateManagerFoldingFeatureProducer.java b/libs/WindowManager/Jetpack/src/androidx/window/common/DeviceStateManagerFoldingFeatureProducer.java index 98935e95deaf..b2bc3de1e7f5 100644 --- a/libs/WindowManager/Jetpack/src/androidx/window/common/DeviceStateManagerFoldingFeatureProducer.java +++ b/libs/WindowManager/Jetpack/src/androidx/window/common/DeviceStateManagerFoldingFeatureProducer.java @@ -31,9 +31,6 @@ import android.text.TextUtils; import android.util.Log; import android.util.SparseIntArray; -import androidx.window.util.AcceptOnceConsumer; -import androidx.window.util.BaseDataProducer; - import com.android.internal.R; import java.util.ArrayList; @@ -44,7 +41,7 @@ import java.util.Optional; import java.util.function.Consumer; /** - * An implementation of {@link androidx.window.util.BaseDataProducer} that returns + * An implementation of {@link BaseDataProducer} that returns * the device's posture by mapping the state returned from {@link DeviceStateManager} to * values provided in the resources' config at {@link R.array#config_device_state_postures}. */ diff --git a/libs/WindowManager/Jetpack/src/androidx/window/util/ExtensionHelper.java b/libs/WindowManager/Jetpack/src/androidx/window/common/ExtensionHelper.java index a08db7939eca..f466d603bda3 100644 --- a/libs/WindowManager/Jetpack/src/androidx/window/util/ExtensionHelper.java +++ b/libs/WindowManager/Jetpack/src/androidx/window/common/ExtensionHelper.java @@ -14,7 +14,7 @@ * limitations under the License. */ -package androidx.window.util; +package androidx.window.common; import static android.view.Surface.ROTATION_270; import static android.view.Surface.ROTATION_90; diff --git a/libs/WindowManager/Jetpack/src/androidx/window/common/RawFoldingFeatureProducer.java b/libs/WindowManager/Jetpack/src/androidx/window/common/RawFoldingFeatureProducer.java index 88264f383153..6d758f1fb3c1 100644 --- a/libs/WindowManager/Jetpack/src/androidx/window/common/RawFoldingFeatureProducer.java +++ b/libs/WindowManager/Jetpack/src/androidx/window/common/RawFoldingFeatureProducer.java @@ -26,15 +26,13 @@ import android.os.Looper; import android.provider.Settings; import android.text.TextUtils; -import androidx.window.util.BaseDataProducer; - import com.android.internal.R; import java.util.Optional; import java.util.function.Consumer; /** - * Implementation of {@link androidx.window.util.BaseDataProducer} that produces a + * Implementation of {@link BaseDataProducer} that produces a * {@link String} that can be parsed to a {@link CommonFoldingFeature}. * {@link RawFoldingFeatureProducer} searches for the value in two places. The first check is in * settings where the {@link String} property is saved with the key diff --git a/libs/WindowManager/Jetpack/src/androidx/window/extensions/embedding/SplitController.java b/libs/WindowManager/Jetpack/src/androidx/window/extensions/embedding/SplitController.java index 8e1fde066277..409cde30cf8c 100644 --- a/libs/WindowManager/Jetpack/src/androidx/window/extensions/embedding/SplitController.java +++ b/libs/WindowManager/Jetpack/src/androidx/window/extensions/embedding/SplitController.java @@ -119,7 +119,8 @@ public class SplitController implements JetpackTaskFragmentOrganizer.TaskFragmen // TODO(b/243518738): Move to WM Extensions if we have requirement of overlay without // association. It's not set in WM Extensions nor Wm Jetpack library currently. - private static final String KEY_OVERLAY_ASSOCIATE_WITH_LAUNCHING_ACTIVITY = + @VisibleForTesting + static final String KEY_OVERLAY_ASSOCIATE_WITH_LAUNCHING_ACTIVITY = "androidx.window.extensions.embedding.shouldAssociateWithLaunchingActivity"; @VisibleForTesting @@ -2742,89 +2743,70 @@ public class SplitController implements JetpackTaskFragmentOrganizer.TaskFragmen } final int taskId = getTaskId(launchActivity); - if (!overlayContainers.isEmpty()) { - for (final TaskFragmentContainer overlayContainer : overlayContainers) { - final boolean isTopNonFinishingOverlay = overlayContainer.equals( - overlayContainer.getTaskContainer().getTopNonFinishingTaskFragmentContainer( - true /* includePin */, true /* includeOverlay */)); - if (taskId != overlayContainer.getTaskId()) { - // If there's an overlay container with same tag in a different task, - // dismiss the overlay container since the tag must be unique per process. - if (overlayTag.equals(overlayContainer.getOverlayTag())) { - Log.w(TAG, "The overlay container with tag:" - + overlayContainer.getOverlayTag() + " is dismissed because" - + " there's an existing overlay container with the same tag but" - + " different task ID:" + overlayContainer.getTaskId() + ". " - + "The new associated activity is " + launchActivity); - mPresenter.cleanupContainer(wct, overlayContainer, - false /* shouldFinishDependant */); - } - continue; - } - if (!overlayTag.equals(overlayContainer.getOverlayTag())) { - // If there's an overlay container with different tag on top in the same - // task, dismiss the existing overlay container. - if (isTopNonFinishingOverlay) { - mPresenter.cleanupContainer(wct, overlayContainer, - false /* shouldFinishDependant */); - } - continue; - } - // The overlay container has the same tag and task ID with the new launching - // overlay container. - if (!isTopNonFinishingOverlay) { - // Dismiss the invisible overlay container regardless of activity - // association if it collides the tag of new launched overlay container . - Log.w(TAG, "The invisible overlay container with tag:" - + overlayContainer.getOverlayTag() + " is dismissed because" - + " there's a launching overlay container with the same tag." - + " The new associated activity is " + launchActivity); - mPresenter.cleanupContainer(wct, overlayContainer, - false /* shouldFinishDependant */); - continue; - } - // Requesting an always-on-top overlay. - if (!associateLaunchingActivity) { - if (overlayContainer.isOverlayWithActivityAssociation()) { - // Dismiss the overlay container since it has associated with an activity. - Log.w(TAG, "The overlay container with tag:" - + overlayContainer.getOverlayTag() + " is dismissed because" - + " there's an existing overlay container with the same tag but" - + " different associated launching activity. The overlay container" - + " doesn't associate with any activity."); - mPresenter.cleanupContainer(wct, overlayContainer, - false /* shouldFinishDependant */); - continue; - } else { - // The existing overlay container doesn't associate an activity as well. - // Just update the overlay and return. - // Note that going to this condition means the tag, task ID matches a - // visible always-on-top overlay, and won't dismiss any overlay any more. - mPresenter.applyActivityStackAttributes(wct, overlayContainer, attrs, - getMinDimensions(intent)); - return overlayContainer; - } - } - if (launchActivity.getActivityToken() - != overlayContainer.getAssociatedActivityToken()) { - Log.w(TAG, "The overlay container with tag:" - + overlayContainer.getOverlayTag() + " is dismissed because" - + " there's an existing overlay container with the same tag but" - + " different associated launching activity. The new associated" - + " activity is " + launchActivity); - // The associated activity must be the same, or it will be dismissed. - mPresenter.cleanupContainer(wct, overlayContainer, - false /* shouldFinishDependant */); - continue; - } - // Reaching here means the launching activity launch an overlay container with the - // same task ID, tag, while there's a previously launching visible overlay - // container. We'll regard it as updating the existing overlay container. + // Overlay container policy: + // 1. Overlay tag must be unique per process. + // a. For associated overlay, if a new launched overlay container has the same tag as + // an existing one, the existing overlay will be dismissed regardless of its task + // and window hierarchy. + // b. For always-on-top overlay, if there's an overlay container has the same tag in the + // launched task, the overlay container will be re-used, which means the + // ActivityStackAttributes will be applied and the launched activity will be positioned + // on top of the overlay container. + // 2. There must be at most one overlay that partially occludes a visible activity per task. + // a. For associated overlay, only the top visible overlay container in the launched task + // will be dismissed. + // b. Always-on-top overlay is always visible. If there's an overlay with different tags + // in the same task, the overlay will be dismissed in case an activity above + // the overlay is dismissed and the overlay is shown unexpectedly. + for (final TaskFragmentContainer overlayContainer : overlayContainers) { + final boolean isTopNonFinishingOverlay = overlayContainer.isTopNonFinishingChild(); + final boolean areInSameTask = taskId == overlayContainer.getTaskId(); + final boolean haveSameTag = overlayTag.equals(overlayContainer.getOverlayTag()); + if (!associateLaunchingActivity && overlayContainer.isAlwaysOnTopOverlay() + && haveSameTag && areInSameTask) { + // Just launch the activity and update the existing always-on-top overlay + // if the requested overlay is an always-on-top overlay with the same tag + // as the existing one. mPresenter.applyActivityStackAttributes(wct, overlayContainer, attrs, getMinDimensions(intent)); return overlayContainer; - } + if (haveSameTag) { + // For other tag match, we should clean up the existing overlay since the overlay + // tag must be unique per process. + Log.w(TAG, "The overlay container with tag:" + + overlayContainer.getOverlayTag() + " is dismissed with " + + " the launching activity=" + launchActivity + + " because there's an existing overlay container with the same tag."); + mPresenter.cleanupContainer(wct, overlayContainer, + false /* shouldFinishDependant */); + } + if (!areInSameTask) { + // Early return here because we won't clean-up or update overlay from different + // tasks except tag collision. + continue; + } + if (associateLaunchingActivity) { + // For associated overlay, we only dismiss the overlay if it's the top non-finishing + // child of its parent container. + if (isTopNonFinishingOverlay) { + Log.w(TAG, "The on-top overlay container with tag:" + + overlayContainer.getOverlayTag() + " is dismissed with " + + " the launching activity=" + launchActivity + + "because we only allow one overlay on top."); + mPresenter.cleanupContainer(wct, overlayContainer, + false /* shouldFinishDependant */); + } + continue; + } + // Otherwise, we should clean up the overlay in the task because we only allow one + // overlay when an always-on-top overlay is launched. + Log.w(TAG, "The overlay container with tag:" + + overlayContainer.getOverlayTag() + " is dismissed with " + + " the launching activity=" + launchActivity + + "because an always-on-top overlay is launched."); + mPresenter.cleanupContainer(wct, overlayContainer, + false /* shouldFinishDependant */); } // Launch the overlay container to the task with taskId. return createEmptyContainer(wct, intent, taskId, attrs, launchActivity, overlayTag, diff --git a/libs/WindowManager/Jetpack/src/androidx/window/extensions/embedding/TaskFragmentContainer.java b/libs/WindowManager/Jetpack/src/androidx/window/extensions/embedding/TaskFragmentContainer.java index 7173b0c95230..d0e2c998e961 100644 --- a/libs/WindowManager/Jetpack/src/androidx/window/extensions/embedding/TaskFragmentContainer.java +++ b/libs/WindowManager/Jetpack/src/androidx/window/extensions/embedding/TaskFragmentContainer.java @@ -340,6 +340,13 @@ class TaskFragmentContainer { return mInfo != null && mInfo.isVisible(); } + /** + * See {@link TaskFragmentInfo#isTopNonFinishingChild()} + */ + boolean isTopNonFinishingChild() { + return mInfo != null && mInfo.isTopNonFinishingChild(); + } + /** Whether the TaskFragment is in an intermediate state waiting for the server update.*/ boolean isInIntermediateState() { if (mInfo == null) { diff --git a/libs/WindowManager/Jetpack/src/androidx/window/extensions/layout/WindowLayoutComponentImpl.java b/libs/WindowManager/Jetpack/src/androidx/window/extensions/layout/WindowLayoutComponentImpl.java index 84984a9f8c7b..a3ef68a15196 100644 --- a/libs/WindowManager/Jetpack/src/androidx/window/extensions/layout/WindowLayoutComponentImpl.java +++ b/libs/WindowManager/Jetpack/src/androidx/window/extensions/layout/WindowLayoutComponentImpl.java @@ -21,9 +21,9 @@ import static android.view.Display.INVALID_DISPLAY; import static androidx.window.common.CommonFoldingFeature.COMMON_STATE_FLAT; import static androidx.window.common.CommonFoldingFeature.COMMON_STATE_HALF_OPENED; -import static androidx.window.util.ExtensionHelper.isZero; -import static androidx.window.util.ExtensionHelper.rotateRectToDisplayRotation; -import static androidx.window.util.ExtensionHelper.transformToWindowSpaceRect; +import static androidx.window.common.ExtensionHelper.isZero; +import static androidx.window.common.ExtensionHelper.rotateRectToDisplayRotation; +import static androidx.window.common.ExtensionHelper.transformToWindowSpaceRect; import android.app.Activity; import android.app.ActivityThread; diff --git a/libs/WindowManager/Jetpack/src/androidx/window/sidecar/SampleSidecarImpl.java b/libs/WindowManager/Jetpack/src/androidx/window/sidecar/SampleSidecarImpl.java index 339908a3a9a4..b63fd0802e5f 100644 --- a/libs/WindowManager/Jetpack/src/androidx/window/sidecar/SampleSidecarImpl.java +++ b/libs/WindowManager/Jetpack/src/androidx/window/sidecar/SampleSidecarImpl.java @@ -25,11 +25,11 @@ import android.os.Bundle; import android.os.IBinder; import androidx.annotation.NonNull; +import androidx.window.common.BaseDataProducer; import androidx.window.common.CommonFoldingFeature; import androidx.window.common.DeviceStateManagerFoldingFeatureProducer; import androidx.window.common.EmptyLifecycleCallbacksAdapter; import androidx.window.common.RawFoldingFeatureProducer; -import androidx.window.util.BaseDataProducer; import java.util.ArrayList; import java.util.List; diff --git a/libs/WindowManager/Jetpack/src/androidx/window/sidecar/SidecarHelper.java b/libs/WindowManager/Jetpack/src/androidx/window/sidecar/SidecarHelper.java index bb6ab47b144d..4fd03e4bdc0b 100644 --- a/libs/WindowManager/Jetpack/src/androidx/window/sidecar/SidecarHelper.java +++ b/libs/WindowManager/Jetpack/src/androidx/window/sidecar/SidecarHelper.java @@ -17,8 +17,8 @@ package androidx.window.sidecar; import static android.view.Display.DEFAULT_DISPLAY; -import static androidx.window.util.ExtensionHelper.rotateRectToDisplayRotation; -import static androidx.window.util.ExtensionHelper.transformToWindowSpaceRect; +import static androidx.window.common.ExtensionHelper.rotateRectToDisplayRotation; +import static androidx.window.common.ExtensionHelper.transformToWindowSpaceRect; import android.annotation.NonNull; import android.app.Activity; diff --git a/libs/WindowManager/Jetpack/tests/unittest/src/androidx/window/util/ExtensionHelperTest.java b/libs/WindowManager/Jetpack/tests/unittest/src/androidx/window/common/ExtensionHelperTest.java index 3278cdf1c337..b6e951961a69 100644 --- a/libs/WindowManager/Jetpack/tests/unittest/src/androidx/window/util/ExtensionHelperTest.java +++ b/libs/WindowManager/Jetpack/tests/unittest/src/androidx/window/common/ExtensionHelperTest.java @@ -14,7 +14,7 @@ * limitations under the License. */ -package androidx.window.util; +package androidx.window.common; import static org.junit.Assert.assertEquals; diff --git a/libs/WindowManager/Jetpack/tests/unittest/src/androidx/window/extensions/embedding/EmbeddingTestUtils.java b/libs/WindowManager/Jetpack/tests/unittest/src/androidx/window/extensions/embedding/EmbeddingTestUtils.java index d649c6d57137..7dc78fdd601f 100644 --- a/libs/WindowManager/Jetpack/tests/unittest/src/androidx/window/extensions/embedding/EmbeddingTestUtils.java +++ b/libs/WindowManager/Jetpack/tests/unittest/src/androidx/window/extensions/embedding/EmbeddingTestUtils.java @@ -163,12 +163,14 @@ public class EmbeddingTestUtils { } /** Creates a mock TaskFragmentInfo for the given TaskFragment. */ + @NonNull static TaskFragmentInfo createMockTaskFragmentInfo(@NonNull TaskFragmentContainer container, @NonNull Activity activity) { return createMockTaskFragmentInfo(container, activity, true /* isVisible */); } /** Creates a mock TaskFragmentInfo for the given TaskFragment. */ + @NonNull static TaskFragmentInfo createMockTaskFragmentInfo(@NonNull TaskFragmentContainer container, @NonNull Activity activity, boolean isVisible) { return new TaskFragmentInfo(container.getTaskFragmentToken(), @@ -182,7 +184,27 @@ public class EmbeddingTestUtils { false /* isTaskClearedForReuse */, false /* isTaskFragmentClearedForPip */, false /* isClearedForReorderActivityToFront */, - new Point()); + new Point(), + false /* isTopChild */); + } + + /** Creates a mock TaskFragmentInfo for the given TaskFragment. */ + @NonNull + static TaskFragmentInfo createMockTaskFragmentInfo(@NonNull TaskFragmentContainer container, + @NonNull Activity activity, boolean isVisible, boolean isOnTop) { + return new TaskFragmentInfo(container.getTaskFragmentToken(), + mock(WindowContainerToken.class), + new Configuration(), + 1, + isVisible, + Collections.singletonList(activity.getActivityToken()), + new ArrayList<>(), + new Point(), + false /* isTaskClearedForReuse */, + false /* isTaskFragmentClearedForPip */, + false /* isClearedForReorderActivityToFront */, + new Point(), + isOnTop); } static ActivityInfo createActivityInfoWithMinDimensions() { diff --git a/libs/WindowManager/Jetpack/tests/unittest/src/androidx/window/extensions/embedding/JetpackTaskFragmentOrganizerTest.java b/libs/WindowManager/Jetpack/tests/unittest/src/androidx/window/extensions/embedding/JetpackTaskFragmentOrganizerTest.java index ad41b18dcbc6..8911d18b9b97 100644 --- a/libs/WindowManager/Jetpack/tests/unittest/src/androidx/window/extensions/embedding/JetpackTaskFragmentOrganizerTest.java +++ b/libs/WindowManager/Jetpack/tests/unittest/src/androidx/window/extensions/embedding/JetpackTaskFragmentOrganizerTest.java @@ -114,6 +114,7 @@ public class JetpackTaskFragmentOrganizerTest { mock(WindowContainerToken.class), new Configuration(), 0 /* runningActivityCount */, false /* isVisible */, new ArrayList<>(), new ArrayList<>(), new Point(), false /* isTaskClearedForReuse */, false /* isTaskFragmentClearedForPip */, - false /* isClearedForReorderActivityToFront */, new Point()); + false /* isClearedForReorderActivityToFront */, new Point(), + false /* isTopChild */); } } diff --git a/libs/WindowManager/Jetpack/tests/unittest/src/androidx/window/extensions/embedding/OverlayPresentationTest.java b/libs/WindowManager/Jetpack/tests/unittest/src/androidx/window/extensions/embedding/OverlayPresentationTest.java index 1c4c8870b26f..475475b05272 100644 --- a/libs/WindowManager/Jetpack/tests/unittest/src/androidx/window/extensions/embedding/OverlayPresentationTest.java +++ b/libs/WindowManager/Jetpack/tests/unittest/src/androidx/window/extensions/embedding/OverlayPresentationTest.java @@ -30,6 +30,7 @@ import static androidx.window.extensions.embedding.EmbeddingTestUtils.createSpli import static androidx.window.extensions.embedding.EmbeddingTestUtils.createSplitPlaceholderRuleBuilder; import static androidx.window.extensions.embedding.EmbeddingTestUtils.createSplitRule; import static androidx.window.extensions.embedding.EmbeddingTestUtils.createTfContainer; +import static androidx.window.extensions.embedding.SplitController.KEY_OVERLAY_ASSOCIATE_WITH_LAUNCHING_ACTIVITY; import static androidx.window.extensions.embedding.SplitPresenter.CONTAINER_POSITION_BOTTOM; import static androidx.window.extensions.embedding.SplitPresenter.CONTAINER_POSITION_LEFT; import static androidx.window.extensions.embedding.SplitPresenter.CONTAINER_POSITION_RIGHT; @@ -94,6 +95,7 @@ import org.junit.Rule; import org.junit.Test; import org.junit.runner.RunWith; import org.mockito.Mock; +import org.mockito.Mockito; import org.mockito.junit.MockitoJUnit; import org.mockito.junit.MockitoRule; @@ -267,7 +269,7 @@ public class OverlayPresentationTest { } @Test - public void testCreateOrUpdateOverlay_visibleOverlaySameTagInTask_dismissOverlay() { + public void testCreateOrUpdateOverlay_topOverlayInTask_dismissOverlay() { createExistingOverlayContainers(); final TaskFragmentContainer overlayContainer = @@ -295,26 +297,6 @@ public class OverlayPresentationTest { } @Test - public void testCreateOrUpdateOverlay_sameTagTaskAndActivity_updateOverlay() { - createExistingOverlayContainers(); - - final Rect bounds = new Rect(0, 0, 100, 100); - mSplitController.setActivityStackAttributesCalculator(params -> - new ActivityStackAttributes.Builder().setRelativeBounds(bounds).build()); - final TaskFragmentContainer overlayContainer = createOrUpdateOverlayTaskFragmentIfNeeded( - mOverlayContainer1.getOverlayTag()); - - assertWithMessage("overlayContainer1 must be updated since the new overlay container" - + " is launched with the same tag and task") - .that(mSplitController.getAllNonFinishingOverlayContainers()) - .containsExactly(mOverlayContainer1, mOverlayContainer2); - - assertThat(overlayContainer).isEqualTo(mOverlayContainer1); - verify(mSplitPresenter).resizeTaskFragment(eq(mTransaction), - eq(mOverlayContainer1.getTaskFragmentToken()), eq(bounds)); - } - - @Test public void testCreateOrUpdateOverlay_sameTagAndTaskButNotActivity_dismissOverlay() { createExistingOverlayContainers(); @@ -362,6 +344,43 @@ public class OverlayPresentationTest { } @Test + public void testCreateOrUpdateAlwaysOnTopOverlay_dismissMultipleOverlaysInTask() { + createExistingOverlayContainers(); + // Create another overlay in task. + final TaskFragmentContainer overlayContainer3 = + createTestOverlayContainer(TASK_ID, "test3"); + assertThat(mSplitController.getAllNonFinishingOverlayContainers()) + .containsExactly(mOverlayContainer1, mOverlayContainer2, overlayContainer3); + + final TaskFragmentContainer overlayContainer = + createOrUpdateAlwaysOnTopOverlay("test4"); + + assertWithMessage("overlayContainer1 and overlayContainer3 must be dismissed") + .that(mSplitController.getAllNonFinishingOverlayContainers()) + .containsExactly(mOverlayContainer2, overlayContainer); + } + + @Test + public void testCreateOrUpdateAlwaysOnTopOverlay_updateOverlay() { + createExistingOverlayContainers(); + // Create another overlay in task. + final TaskFragmentContainer alwaysOnTopOverlay = createTestOverlayContainer(TASK_ID, + "test3", true /* isVisible */, false /* associateLaunchingActivity */); + final ActivityStackAttributes attrs = new ActivityStackAttributes.Builder() + .setRelativeBounds(new Rect(0, 0, 100, 100)).build(); + mSplitController.setActivityStackAttributesCalculator(params -> attrs); + + Mockito.clearInvocations(mSplitPresenter); + final TaskFragmentContainer overlayContainer = + createOrUpdateAlwaysOnTopOverlay(alwaysOnTopOverlay.getOverlayTag()); + + assertWithMessage("overlayContainer1 and overlayContainer3 must be dismissed") + .that(mSplitController.getAllNonFinishingOverlayContainers()) + .containsExactly(mOverlayContainer2, alwaysOnTopOverlay); + assertThat(overlayContainer).isEqualTo(alwaysOnTopOverlay); + } + + @Test public void testCreateOrUpdateOverlay_launchFromSplit_returnNull() { final Activity primaryActivity = createMockActivity(); final Activity secondaryActivity = createMockActivity(); @@ -381,13 +400,13 @@ public class OverlayPresentationTest { } private void createExistingOverlayContainers() { - createExistingOverlayContainers(true /* visible */); + createExistingOverlayContainers(true /* isOnTop */); } - private void createExistingOverlayContainers(boolean visible) { - mOverlayContainer1 = createTestOverlayContainer(TASK_ID, "test1", visible, + private void createExistingOverlayContainers(boolean isOnTop) { + mOverlayContainer1 = createTestOverlayContainer(TASK_ID, "test1", isOnTop, true /* associatedLaunchingActivity */, mActivity); - mOverlayContainer2 = createTestOverlayContainer(TASK_ID + 1, "test2", visible); + mOverlayContainer2 = createTestOverlayContainer(TASK_ID + 1, "test2", isOnTop); List<TaskFragmentContainer> overlayContainers = mSplitController .getAllNonFinishingOverlayContainers(); assertThat(overlayContainers).containsExactly(mOverlayContainer1, mOverlayContainer2); @@ -966,6 +985,16 @@ public class OverlayPresentationTest { launchOptions, mIntent, activity); } + @Nullable + private TaskFragmentContainer createOrUpdateAlwaysOnTopOverlay( + @NonNull String tag) { + final Bundle launchOptions = new Bundle(); + launchOptions.putBoolean(KEY_OVERLAY_ASSOCIATE_WITH_LAUNCHING_ACTIVITY, false); + launchOptions.putString(KEY_OVERLAY_TAG, tag); + return mSplitController.createOrUpdateOverlayTaskFragmentIfNeeded(mTransaction, + launchOptions, mIntent, createMockActivity()); + } + /** Creates a mock TaskFragment that has been registered and appeared in the organizer. */ @NonNull private TaskFragmentContainer createMockTaskFragmentContainer(@NonNull Activity activity) { @@ -975,10 +1004,10 @@ public class OverlayPresentationTest { /** Creates a mock TaskFragment that has been registered and appeared in the organizer. */ @NonNull private TaskFragmentContainer createMockTaskFragmentContainer( - @NonNull Activity activity, boolean isVisible) { + @NonNull Activity activity, boolean isOnTop) { final TaskFragmentContainer container = createTfContainer(mSplitController, activity.getTaskId(), activity); - setupTaskFragmentInfo(container, activity, isVisible); + setupTaskFragmentInfo(container, activity, isOnTop); return container; } @@ -990,8 +1019,8 @@ public class OverlayPresentationTest { @NonNull private TaskFragmentContainer createTestOverlayContainer(int taskId, @NonNull String tag, - boolean isVisible) { - return createTestOverlayContainer(taskId, tag, isVisible, + boolean isOnTop) { + return createTestOverlayContainer(taskId, tag, isOnTop, true /* associateLaunchingActivity */); } @@ -1002,11 +1031,9 @@ public class OverlayPresentationTest { null /* launchingActivity */); } - // TODO(b/243518738): add more test coverage on overlay container without activity association - // once we have use cases. @NonNull private TaskFragmentContainer createTestOverlayContainer(int taskId, @NonNull String tag, - boolean isVisible, boolean associateLaunchingActivity, + boolean isOnTop, boolean associateLaunchingActivity, @Nullable Activity launchingActivity) { final Activity activity = launchingActivity != null ? launchingActivity : createMockActivity(); @@ -1017,14 +1044,15 @@ public class OverlayPresentationTest { .setLaunchOptions(Bundle.EMPTY) .setAssociatedActivity(associateLaunchingActivity ? activity : null) .build(); - setupTaskFragmentInfo(overlayContainer, createMockActivity(), isVisible); + setupTaskFragmentInfo(overlayContainer, createMockActivity(), isOnTop); return overlayContainer; } private void setupTaskFragmentInfo(@NonNull TaskFragmentContainer container, @NonNull Activity activity, - boolean isVisible) { - final TaskFragmentInfo info = createMockTaskFragmentInfo(container, activity, isVisible); + boolean isOnTop) { + final TaskFragmentInfo info = createMockTaskFragmentInfo(container, activity, isOnTop, + isOnTop); container.setInfo(mTransaction, info); mSplitPresenter.mFragmentInfos.put(container.getTaskFragmentToken(), info); } diff --git a/libs/WindowManager/Shell/res/layout/compat_ui_layout.xml b/libs/WindowManager/Shell/res/layout/compat_ui_layout.xml index 257fe1544bbb..62782a784db9 100644 --- a/libs/WindowManager/Shell/res/layout/compat_ui_layout.xml +++ b/libs/WindowManager/Shell/res/layout/compat_ui_layout.xml @@ -21,38 +21,6 @@ android:orientation="vertical" android:gravity="bottom|end"> - <include android:id="@+id/camera_compat_hint" - android:visibility="gone" - android:layout_width="@dimen/camera_compat_hint_width" - android:layout_height="wrap_content" - layout="@layout/compat_mode_hint"/> - - <LinearLayout - android:id="@+id/camera_compat_control" - android:visibility="gone" - android:layout_width="wrap_content" - android:layout_height="wrap_content" - android:clipToPadding="false" - android:layout_marginEnd="@dimen/compat_button_margin" - android:layout_marginBottom="@dimen/compat_button_margin" - android:orientation="vertical"> - - <ImageButton - android:id="@+id/camera_compat_treatment_button" - android:layout_width="wrap_content" - android:layout_height="wrap_content" - android:background="@android:color/transparent"/> - - <ImageButton - android:id="@+id/camera_compat_dismiss_button" - android:layout_width="wrap_content" - android:layout_height="wrap_content" - android:src="@drawable/camera_compat_dismiss_ripple" - android:background="@android:color/transparent" - android:contentDescription="@string/camera_compat_dismiss_button_description"/> - - </LinearLayout> - <include android:id="@+id/size_compat_hint" android:visibility="gone" android:layout_width="@dimen/compat_hint_width" diff --git a/libs/WindowManager/Shell/res/values-af/strings.xml b/libs/WindowManager/Shell/res/values-af/strings.xml index e476db050f01..e58ff6aa331e 100644 --- a/libs/WindowManager/Shell/res/values-af/strings.xml +++ b/libs/WindowManager/Shell/res/values-af/strings.xml @@ -107,7 +107,7 @@ <string name="minimize_button_text" msgid="271592547935841753">"Maak klein"</string> <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> + <string name="handle_text" msgid="4419667835599523257">"Apphandvatsel"</string> <string name="app_icon_text" msgid="2823268023931811747">"Appikoon"</string> <string name="fullscreen_text" msgid="1162316685217676079">"Volskerm"</string> <string name="desktop_text" msgid="1077633567027630454">"Rekenaarmodus"</string> diff --git a/libs/WindowManager/Shell/res/values-am/strings.xml b/libs/WindowManager/Shell/res/values-am/strings.xml index 33fea2bcdde5..3208ea9bea61 100644 --- a/libs/WindowManager/Shell/res/values-am/strings.xml +++ b/libs/WindowManager/Shell/res/values-am/strings.xml @@ -107,7 +107,7 @@ <string name="minimize_button_text" msgid="271592547935841753">"አሳንስ"</string> <string name="close_button_text" msgid="2913281996024033299">"ዝጋ"</string> <string name="back_button_text" msgid="1469718707134137085">"ተመለስ"</string> - <string name="handle_text" msgid="1766582106752184456">"መያዣ"</string> + <string name="handle_text" msgid="4419667835599523257">"የመተግበሪያ መያዣ"</string> <string name="app_icon_text" msgid="2823268023931811747">"የመተግበሪያ አዶ"</string> <string name="fullscreen_text" msgid="1162316685217676079">"ሙሉ ማያ"</string> <string name="desktop_text" msgid="1077633567027630454">"የዴስክቶፕ ሁነታ"</string> diff --git a/libs/WindowManager/Shell/res/values-ar/strings.xml b/libs/WindowManager/Shell/res/values-ar/strings.xml index b014c3ba7d77..18db50ecdadd 100644 --- a/libs/WindowManager/Shell/res/values-ar/strings.xml +++ b/libs/WindowManager/Shell/res/values-ar/strings.xml @@ -107,7 +107,7 @@ <string name="minimize_button_text" msgid="271592547935841753">"تصغير"</string> <string name="close_button_text" msgid="2913281996024033299">"إغلاق"</string> <string name="back_button_text" msgid="1469718707134137085">"رجوع"</string> - <string name="handle_text" msgid="1766582106752184456">"مقبض"</string> + <string name="handle_text" msgid="4419667835599523257">"مقبض التطبيق"</string> <string name="app_icon_text" msgid="2823268023931811747">"رمز التطبيق"</string> <string name="fullscreen_text" msgid="1162316685217676079">"ملء الشاشة"</string> <string name="desktop_text" msgid="1077633567027630454">"وضع سطح المكتب"</string> diff --git a/libs/WindowManager/Shell/res/values-as/strings.xml b/libs/WindowManager/Shell/res/values-as/strings.xml index b94ab2e73e9c..195177230419 100644 --- a/libs/WindowManager/Shell/res/values-as/strings.xml +++ b/libs/WindowManager/Shell/res/values-as/strings.xml @@ -107,7 +107,7 @@ <string name="minimize_button_text" msgid="271592547935841753">"মিনিমাইজ কৰক"</string> <string name="close_button_text" msgid="2913281996024033299">"বন্ধ কৰক"</string> <string name="back_button_text" msgid="1469718707134137085">"উভতি যাওক"</string> - <string name="handle_text" msgid="1766582106752184456">"হেণ্ডেল"</string> + <string name="handle_text" msgid="4419667835599523257">"এপৰ হেণ্ডেল"</string> <string name="app_icon_text" msgid="2823268023931811747">"এপৰ চিহ্ন"</string> <string name="fullscreen_text" msgid="1162316685217676079">"সম্পূৰ্ণ স্ক্ৰীন"</string> <string name="desktop_text" msgid="1077633567027630454">"ডেস্কটপ ম’ড"</string> diff --git a/libs/WindowManager/Shell/res/values-az/strings.xml b/libs/WindowManager/Shell/res/values-az/strings.xml index 9ec44a1e6325..32e0dd698571 100644 --- a/libs/WindowManager/Shell/res/values-az/strings.xml +++ b/libs/WindowManager/Shell/res/values-az/strings.xml @@ -107,7 +107,7 @@ <string name="minimize_button_text" msgid="271592547935841753">"Kiçildin"</string> <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> + <string name="handle_text" msgid="4419667835599523257">"Tətbiq ləqəbi"</string> <string name="app_icon_text" msgid="2823268023931811747">"Tətbiq ikonası"</string> <string name="fullscreen_text" msgid="1162316685217676079">"Tam Ekran"</string> <string name="desktop_text" msgid="1077633567027630454">"Masaüstü Rejimi"</string> 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 af695e73161d..1656e02b476a 100644 --- a/libs/WindowManager/Shell/res/values-b+sr+Latn/strings.xml +++ b/libs/WindowManager/Shell/res/values-b+sr+Latn/strings.xml @@ -107,7 +107,7 @@ <string name="minimize_button_text" msgid="271592547935841753">"Umanjite"</string> <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> + <string name="handle_text" msgid="4419667835599523257">"Identifikator aplikacije"</string> <string name="app_icon_text" msgid="2823268023931811747">"Ikona aplikacije"</string> <string name="fullscreen_text" msgid="1162316685217676079">"Preko celog ekrana"</string> <string name="desktop_text" msgid="1077633567027630454">"Režim za računare"</string> diff --git a/libs/WindowManager/Shell/res/values-be/strings.xml b/libs/WindowManager/Shell/res/values-be/strings.xml index dbbc07fe2407..26f3d3ce85e3 100644 --- a/libs/WindowManager/Shell/res/values-be/strings.xml +++ b/libs/WindowManager/Shell/res/values-be/strings.xml @@ -107,7 +107,7 @@ <string name="minimize_button_text" msgid="271592547935841753">"Згарнуць"</string> <string name="close_button_text" msgid="2913281996024033299">"Закрыць"</string> <string name="back_button_text" msgid="1469718707134137085">"Назад"</string> - <string name="handle_text" msgid="1766582106752184456">"Маркер"</string> + <string name="handle_text" msgid="4419667835599523257">"Маркер праграмы"</string> <string name="app_icon_text" msgid="2823268023931811747">"Значок праграмы"</string> <string name="fullscreen_text" msgid="1162316685217676079">"На ўвесь экран"</string> <string name="desktop_text" msgid="1077633567027630454">"Рэжым працоўнага стала"</string> diff --git a/libs/WindowManager/Shell/res/values-bg/strings.xml b/libs/WindowManager/Shell/res/values-bg/strings.xml index 8dc791501b1b..7c4f25efb7e3 100644 --- a/libs/WindowManager/Shell/res/values-bg/strings.xml +++ b/libs/WindowManager/Shell/res/values-bg/strings.xml @@ -107,7 +107,7 @@ <string name="minimize_button_text" msgid="271592547935841753">"Намаляване"</string> <string name="close_button_text" msgid="2913281996024033299">"Затваряне"</string> <string name="back_button_text" msgid="1469718707134137085">"Назад"</string> - <string name="handle_text" msgid="1766582106752184456">"Манипулатор"</string> + <string name="handle_text" msgid="4419667835599523257">"Манипулатор за приложението"</string> <string name="app_icon_text" msgid="2823268023931811747">"Икона на приложението"</string> <string name="fullscreen_text" msgid="1162316685217676079">"Цял екран"</string> <string name="desktop_text" msgid="1077633567027630454">"Режим за настолни компютри"</string> diff --git a/libs/WindowManager/Shell/res/values-bn/strings.xml b/libs/WindowManager/Shell/res/values-bn/strings.xml index 61294ada298e..4286162c0c87 100644 --- a/libs/WindowManager/Shell/res/values-bn/strings.xml +++ b/libs/WindowManager/Shell/res/values-bn/strings.xml @@ -107,7 +107,7 @@ <string name="minimize_button_text" msgid="271592547935841753">"ছোট করুন"</string> <string name="close_button_text" msgid="2913281996024033299">"বন্ধ করুন"</string> <string name="back_button_text" msgid="1469718707134137085">"ফিরে যান"</string> - <string name="handle_text" msgid="1766582106752184456">"হাতল"</string> + <string name="handle_text" msgid="4419667835599523257">"অ্যাপের হ্যান্ডেল"</string> <string name="app_icon_text" msgid="2823268023931811747">"অ্যাপ আইকন"</string> <string name="fullscreen_text" msgid="1162316685217676079">"ফুলস্ক্রিন"</string> <string name="desktop_text" msgid="1077633567027630454">"ডেস্কটপ মোড"</string> diff --git a/libs/WindowManager/Shell/res/values-bs/strings.xml b/libs/WindowManager/Shell/res/values-bs/strings.xml index 676b226ec8c1..11f5e480f7db 100644 --- a/libs/WindowManager/Shell/res/values-bs/strings.xml +++ b/libs/WindowManager/Shell/res/values-bs/strings.xml @@ -107,7 +107,7 @@ <string name="minimize_button_text" msgid="271592547935841753">"Minimiziranje"</string> <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="handle_text" msgid="4419667835599523257">"Ručica aplikacije"</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> diff --git a/libs/WindowManager/Shell/res/values-ca/strings.xml b/libs/WindowManager/Shell/res/values-ca/strings.xml index ce9f54798120..e1fc7d38a527 100644 --- a/libs/WindowManager/Shell/res/values-ca/strings.xml +++ b/libs/WindowManager/Shell/res/values-ca/strings.xml @@ -107,7 +107,7 @@ <string name="minimize_button_text" msgid="271592547935841753">"Minimitza"</string> <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> + <string name="handle_text" msgid="4419667835599523257">"Identificador de l\'aplicació"</string> <string name="app_icon_text" msgid="2823268023931811747">"Icona de l\'aplicació"</string> <string name="fullscreen_text" msgid="1162316685217676079">"Pantalla completa"</string> <string name="desktop_text" msgid="1077633567027630454">"Mode d\'escriptori"</string> diff --git a/libs/WindowManager/Shell/res/values-cs/strings.xml b/libs/WindowManager/Shell/res/values-cs/strings.xml index 6b9d85f37f00..e4282105455e 100644 --- a/libs/WindowManager/Shell/res/values-cs/strings.xml +++ b/libs/WindowManager/Shell/res/values-cs/strings.xml @@ -107,7 +107,7 @@ <string name="minimize_button_text" msgid="271592547935841753">"Minimalizovat"</string> <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> + <string name="handle_text" msgid="4419667835599523257">"Popisovač aplikace"</string> <string name="app_icon_text" msgid="2823268023931811747">"Ikona aplikace"</string> <string name="fullscreen_text" msgid="1162316685217676079">"Celá obrazovka"</string> <string name="desktop_text" msgid="1077633567027630454">"Režim počítače"</string> diff --git a/libs/WindowManager/Shell/res/values-da/strings.xml b/libs/WindowManager/Shell/res/values-da/strings.xml index de7d91943a4d..36c03304a670 100644 --- a/libs/WindowManager/Shell/res/values-da/strings.xml +++ b/libs/WindowManager/Shell/res/values-da/strings.xml @@ -107,7 +107,7 @@ <string name="minimize_button_text" msgid="271592547935841753">"Minimer"</string> <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> + <string name="handle_text" msgid="4419667835599523257">"Apphåndtag"</string> <string name="app_icon_text" msgid="2823268023931811747">"Appikon"</string> <string name="fullscreen_text" msgid="1162316685217676079">"Fuld skærm"</string> <string name="desktop_text" msgid="1077633567027630454">"Computertilstand"</string> diff --git a/libs/WindowManager/Shell/res/values-de/strings.xml b/libs/WindowManager/Shell/res/values-de/strings.xml index e4fd3118293f..0ad112cf87a7 100644 --- a/libs/WindowManager/Shell/res/values-de/strings.xml +++ b/libs/WindowManager/Shell/res/values-de/strings.xml @@ -107,7 +107,7 @@ <string name="minimize_button_text" msgid="271592547935841753">"Minimieren"</string> <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> + <string name="handle_text" msgid="4419667835599523257">"App-Ziehpunkt"</string> <string name="app_icon_text" msgid="2823268023931811747">"App-Symbol"</string> <string name="fullscreen_text" msgid="1162316685217676079">"Vollbild"</string> <string name="desktop_text" msgid="1077633567027630454">"Desktopmodus"</string> diff --git a/libs/WindowManager/Shell/res/values-el/strings.xml b/libs/WindowManager/Shell/res/values-el/strings.xml index 964166e16034..1e2fec19c639 100644 --- a/libs/WindowManager/Shell/res/values-el/strings.xml +++ b/libs/WindowManager/Shell/res/values-el/strings.xml @@ -107,7 +107,7 @@ <string name="minimize_button_text" msgid="271592547935841753">"Ελαχιστοποίηση"</string> <string name="close_button_text" msgid="2913281996024033299">"Κλείσιμο"</string> <string name="back_button_text" msgid="1469718707134137085">"Πίσω"</string> - <string name="handle_text" msgid="1766582106752184456">"Λαβή"</string> + <string name="handle_text" msgid="4419667835599523257">"Λαβή εφαρμογής"</string> <string name="app_icon_text" msgid="2823268023931811747">"Εικονίδιο εφαρμογής"</string> <string name="fullscreen_text" msgid="1162316685217676079">"Πλήρης οθόνη"</string> <string name="desktop_text" msgid="1077633567027630454">"Λειτουργία επιφάνειας εργασίας"</string> diff --git a/libs/WindowManager/Shell/res/values-en-rAU/strings.xml b/libs/WindowManager/Shell/res/values-en-rAU/strings.xml index c17b9f7ad8dc..71701c9a18a1 100644 --- a/libs/WindowManager/Shell/res/values-en-rAU/strings.xml +++ b/libs/WindowManager/Shell/res/values-en-rAU/strings.xml @@ -107,7 +107,7 @@ <string name="minimize_button_text" msgid="271592547935841753">"Minimise"</string> <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="handle_text" msgid="4419667835599523257">"App 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> diff --git a/libs/WindowManager/Shell/res/values-en-rCA/strings.xml b/libs/WindowManager/Shell/res/values-en-rCA/strings.xml index bd8a63690ba3..5ab4af3d1557 100644 --- a/libs/WindowManager/Shell/res/values-en-rCA/strings.xml +++ b/libs/WindowManager/Shell/res/values-en-rCA/strings.xml @@ -107,7 +107,7 @@ <string name="minimize_button_text" msgid="271592547935841753">"Minimize"</string> <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="handle_text" msgid="4419667835599523257">"App 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> diff --git a/libs/WindowManager/Shell/res/values-en-rGB/strings.xml b/libs/WindowManager/Shell/res/values-en-rGB/strings.xml index c17b9f7ad8dc..71701c9a18a1 100644 --- a/libs/WindowManager/Shell/res/values-en-rGB/strings.xml +++ b/libs/WindowManager/Shell/res/values-en-rGB/strings.xml @@ -107,7 +107,7 @@ <string name="minimize_button_text" msgid="271592547935841753">"Minimise"</string> <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="handle_text" msgid="4419667835599523257">"App 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> diff --git a/libs/WindowManager/Shell/res/values-en-rIN/strings.xml b/libs/WindowManager/Shell/res/values-en-rIN/strings.xml index c17b9f7ad8dc..71701c9a18a1 100644 --- a/libs/WindowManager/Shell/res/values-en-rIN/strings.xml +++ b/libs/WindowManager/Shell/res/values-en-rIN/strings.xml @@ -107,7 +107,7 @@ <string name="minimize_button_text" msgid="271592547935841753">"Minimise"</string> <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="handle_text" msgid="4419667835599523257">"App 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> diff --git a/libs/WindowManager/Shell/res/values-en-rXC/strings.xml b/libs/WindowManager/Shell/res/values-en-rXC/strings.xml index 35030808f4fd..42d5f068927b 100644 --- a/libs/WindowManager/Shell/res/values-en-rXC/strings.xml +++ b/libs/WindowManager/Shell/res/values-en-rXC/strings.xml @@ -107,7 +107,7 @@ <string name="minimize_button_text" msgid="271592547935841753">"Minimize"</string> <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="handle_text" msgid="4419667835599523257">"App 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> diff --git a/libs/WindowManager/Shell/res/values-es-rUS/strings.xml b/libs/WindowManager/Shell/res/values-es-rUS/strings.xml index 049649f0c748..1e3091295460 100644 --- a/libs/WindowManager/Shell/res/values-es-rUS/strings.xml +++ b/libs/WindowManager/Shell/res/values-es-rUS/strings.xml @@ -107,7 +107,7 @@ <string name="minimize_button_text" msgid="271592547935841753">"Minimizar"</string> <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> + <string name="handle_text" msgid="4419667835599523257">"Controlador de la app"</string> <string name="app_icon_text" msgid="2823268023931811747">"Ícono de la app"</string> <string name="fullscreen_text" msgid="1162316685217676079">"Pantalla completa"</string> <string name="desktop_text" msgid="1077633567027630454">"Modo de escritorio"</string> diff --git a/libs/WindowManager/Shell/res/values-es/strings.xml b/libs/WindowManager/Shell/res/values-es/strings.xml index 77413186228d..312e2977b4c3 100644 --- a/libs/WindowManager/Shell/res/values-es/strings.xml +++ b/libs/WindowManager/Shell/res/values-es/strings.xml @@ -107,7 +107,7 @@ <string name="minimize_button_text" msgid="271592547935841753">"Minimizar"</string> <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> + <string name="handle_text" msgid="4419667835599523257">"Controlador de la aplicación"</string> <string name="app_icon_text" msgid="2823268023931811747">"Icono de la aplicación"</string> <string name="fullscreen_text" msgid="1162316685217676079">"Pantalla completa"</string> <string name="desktop_text" msgid="1077633567027630454">"Modo Escritorio"</string> diff --git a/libs/WindowManager/Shell/res/values-et/strings.xml b/libs/WindowManager/Shell/res/values-et/strings.xml index 29fc150fd229..5e4ef81c7795 100644 --- a/libs/WindowManager/Shell/res/values-et/strings.xml +++ b/libs/WindowManager/Shell/res/values-et/strings.xml @@ -107,7 +107,7 @@ <string name="minimize_button_text" msgid="271592547935841753">"Minimeeri"</string> <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> + <string name="handle_text" msgid="4419667835599523257">"Rakenduse element"</string> <string name="app_icon_text" msgid="2823268023931811747">"Rakenduse ikoon"</string> <string name="fullscreen_text" msgid="1162316685217676079">"Täisekraan"</string> <string name="desktop_text" msgid="1077633567027630454">"Lauaarvuti režiim"</string> diff --git a/libs/WindowManager/Shell/res/values-eu/strings.xml b/libs/WindowManager/Shell/res/values-eu/strings.xml index 580f6e1cd875..40d67a2a9a9d 100644 --- a/libs/WindowManager/Shell/res/values-eu/strings.xml +++ b/libs/WindowManager/Shell/res/values-eu/strings.xml @@ -107,7 +107,7 @@ <string name="minimize_button_text" msgid="271592547935841753">"Minimizatu"</string> <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> + <string name="handle_text" msgid="4419667835599523257">"Aplikazioaren kontrol-puntua"</string> <string name="app_icon_text" msgid="2823268023931811747">"Aplikazioaren ikonoa"</string> <string name="fullscreen_text" msgid="1162316685217676079">"Pantaila osoa"</string> <string name="desktop_text" msgid="1077633567027630454">"Ordenagailuetarako modua"</string> diff --git a/libs/WindowManager/Shell/res/values-fa/strings.xml b/libs/WindowManager/Shell/res/values-fa/strings.xml index 766e78734fbc..55da319031e3 100644 --- a/libs/WindowManager/Shell/res/values-fa/strings.xml +++ b/libs/WindowManager/Shell/res/values-fa/strings.xml @@ -107,7 +107,7 @@ <string name="minimize_button_text" msgid="271592547935841753">"کوچک کردن"</string> <string name="close_button_text" msgid="2913281996024033299">"بستن"</string> <string name="back_button_text" msgid="1469718707134137085">"برگشتن"</string> - <string name="handle_text" msgid="1766582106752184456">"دستگیره"</string> + <string name="handle_text" msgid="4419667835599523257">"دستگیره برنامه"</string> <string name="app_icon_text" msgid="2823268023931811747">"نماد برنامه"</string> <string name="fullscreen_text" msgid="1162316685217676079">"تمامصفحه"</string> <string name="desktop_text" msgid="1077633567027630454">"حالت رایانه"</string> diff --git a/libs/WindowManager/Shell/res/values-fi/strings.xml b/libs/WindowManager/Shell/res/values-fi/strings.xml index 96c7b7504724..c2610ff182f2 100644 --- a/libs/WindowManager/Shell/res/values-fi/strings.xml +++ b/libs/WindowManager/Shell/res/values-fi/strings.xml @@ -107,7 +107,7 @@ <string name="minimize_button_text" msgid="271592547935841753">"Pienennä"</string> <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> + <string name="handle_text" msgid="4419667835599523257">"Sovelluksen tunnus"</string> <string name="app_icon_text" msgid="2823268023931811747">"Sovelluskuvake"</string> <string name="fullscreen_text" msgid="1162316685217676079">"Koko näyttö"</string> <string name="desktop_text" msgid="1077633567027630454">"Työpöytätila"</string> diff --git a/libs/WindowManager/Shell/res/values-fr-rCA/strings.xml b/libs/WindowManager/Shell/res/values-fr-rCA/strings.xml index e54e59d279fd..7a59b62812b9 100644 --- a/libs/WindowManager/Shell/res/values-fr-rCA/strings.xml +++ b/libs/WindowManager/Shell/res/values-fr-rCA/strings.xml @@ -107,7 +107,7 @@ <string name="minimize_button_text" msgid="271592547935841753">"Réduire"</string> <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> + <string name="handle_text" msgid="4419667835599523257">"Poignée de l\'appli"</string> <string name="app_icon_text" msgid="2823268023931811747">"Icône de l\'appli"</string> <string name="fullscreen_text" msgid="1162316685217676079">"Plein écran"</string> <string name="desktop_text" msgid="1077633567027630454">"Mode Bureau"</string> diff --git a/libs/WindowManager/Shell/res/values-fr/strings.xml b/libs/WindowManager/Shell/res/values-fr/strings.xml index d150ad7e89f5..0cf944fca1e6 100644 --- a/libs/WindowManager/Shell/res/values-fr/strings.xml +++ b/libs/WindowManager/Shell/res/values-fr/strings.xml @@ -107,7 +107,7 @@ <string name="minimize_button_text" msgid="271592547935841753">"Réduire"</string> <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> + <string name="handle_text" msgid="4419667835599523257">"Poignée de l\'appli"</string> <string name="app_icon_text" msgid="2823268023931811747">"Icône d\'application"</string> <string name="fullscreen_text" msgid="1162316685217676079">"Plein écran"</string> <string name="desktop_text" msgid="1077633567027630454">"Mode ordinateur"</string> diff --git a/libs/WindowManager/Shell/res/values-gl/strings.xml b/libs/WindowManager/Shell/res/values-gl/strings.xml index 6429fb31acd7..0f2a6010c860 100644 --- a/libs/WindowManager/Shell/res/values-gl/strings.xml +++ b/libs/WindowManager/Shell/res/values-gl/strings.xml @@ -107,7 +107,7 @@ <string name="minimize_button_text" msgid="271592547935841753">"Minimizar"</string> <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> + <string name="handle_text" msgid="4419667835599523257">"Controlador da aplicación"</string> <string name="app_icon_text" msgid="2823268023931811747">"Icona de aplicación"</string> <string name="fullscreen_text" msgid="1162316685217676079">"Pantalla completa"</string> <string name="desktop_text" msgid="1077633567027630454">"Modo de escritorio"</string> diff --git a/libs/WindowManager/Shell/res/values-gu/strings.xml b/libs/WindowManager/Shell/res/values-gu/strings.xml index f8bdfaeccc15..6151da03797c 100644 --- a/libs/WindowManager/Shell/res/values-gu/strings.xml +++ b/libs/WindowManager/Shell/res/values-gu/strings.xml @@ -107,7 +107,7 @@ <string name="minimize_button_text" msgid="271592547935841753">"નાનું કરો"</string> <string name="close_button_text" msgid="2913281996024033299">"બંધ કરો"</string> <string name="back_button_text" msgid="1469718707134137085">"પાછળ"</string> - <string name="handle_text" msgid="1766582106752184456">"હૅન્ડલ"</string> + <string name="handle_text" msgid="4419667835599523257">"ઍપનું હૅન્ડલ"</string> <string name="app_icon_text" msgid="2823268023931811747">"ઍપનું આઇકન"</string> <string name="fullscreen_text" msgid="1162316685217676079">"પૂર્ણસ્ક્રીન"</string> <string name="desktop_text" msgid="1077633567027630454">"ડેસ્કટૉપ મોડ"</string> diff --git a/libs/WindowManager/Shell/res/values-hi/strings.xml b/libs/WindowManager/Shell/res/values-hi/strings.xml index d7c380387509..04e76bc5bed3 100644 --- a/libs/WindowManager/Shell/res/values-hi/strings.xml +++ b/libs/WindowManager/Shell/res/values-hi/strings.xml @@ -107,7 +107,7 @@ <string name="minimize_button_text" msgid="271592547935841753">"विंडो छोटी करें"</string> <string name="close_button_text" msgid="2913281996024033299">"बंद करें"</string> <string name="back_button_text" msgid="1469718707134137085">"वापस जाएं"</string> - <string name="handle_text" msgid="1766582106752184456">"हैंडल"</string> + <string name="handle_text" msgid="4419667835599523257">"ऐप्लिकेशन का हैंडल"</string> <string name="app_icon_text" msgid="2823268023931811747">"ऐप्लिकेशन आइकॉन"</string> <string name="fullscreen_text" msgid="1162316685217676079">"फ़ुलस्क्रीन"</string> <string name="desktop_text" msgid="1077633567027630454">"डेस्कटॉप मोड"</string> diff --git a/libs/WindowManager/Shell/res/values-hr/strings.xml b/libs/WindowManager/Shell/res/values-hr/strings.xml index 000b0e63bf8e..aa2ee17a157f 100644 --- a/libs/WindowManager/Shell/res/values-hr/strings.xml +++ b/libs/WindowManager/Shell/res/values-hr/strings.xml @@ -107,7 +107,7 @@ <string name="minimize_button_text" msgid="271592547935841753">"Minimiziraj"</string> <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="handle_text" msgid="4419667835599523257">"Pokazivač aplikacije"</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> diff --git a/libs/WindowManager/Shell/res/values-hu/strings.xml b/libs/WindowManager/Shell/res/values-hu/strings.xml index b1268cc849ab..8ffeeed1b1f3 100644 --- a/libs/WindowManager/Shell/res/values-hu/strings.xml +++ b/libs/WindowManager/Shell/res/values-hu/strings.xml @@ -107,7 +107,7 @@ <string name="minimize_button_text" msgid="271592547935841753">"Kis méret"</string> <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> + <string name="handle_text" msgid="4419667835599523257">"App fogópontja"</string> <string name="app_icon_text" msgid="2823268023931811747">"Alkalmazásikon"</string> <string name="fullscreen_text" msgid="1162316685217676079">"Teljes képernyő"</string> <string name="desktop_text" msgid="1077633567027630454">"Asztali üzemmód"</string> diff --git a/libs/WindowManager/Shell/res/values-hy/strings.xml b/libs/WindowManager/Shell/res/values-hy/strings.xml index 1d2d2ff76912..b3fccfaa93f1 100644 --- a/libs/WindowManager/Shell/res/values-hy/strings.xml +++ b/libs/WindowManager/Shell/res/values-hy/strings.xml @@ -107,7 +107,7 @@ <string name="minimize_button_text" msgid="271592547935841753">"Ծալել"</string> <string name="close_button_text" msgid="2913281996024033299">"Փակել"</string> <string name="back_button_text" msgid="1469718707134137085">"Հետ"</string> - <string name="handle_text" msgid="1766582106752184456">"Նշիչ"</string> + <string name="handle_text" msgid="4419667835599523257">"Հավելվածի կեղծանուն"</string> <string name="app_icon_text" msgid="2823268023931811747">"Հավելվածի պատկերակ"</string> <string name="fullscreen_text" msgid="1162316685217676079">"Լիաէկրան"</string> <string name="desktop_text" msgid="1077633567027630454">"Համակարգչի ռեժիմ"</string> diff --git a/libs/WindowManager/Shell/res/values-in/strings.xml b/libs/WindowManager/Shell/res/values-in/strings.xml index 17e91050584d..38b24f92b76d 100644 --- a/libs/WindowManager/Shell/res/values-in/strings.xml +++ b/libs/WindowManager/Shell/res/values-in/strings.xml @@ -107,7 +107,7 @@ <string name="minimize_button_text" msgid="271592547935841753">"Minimalkan"</string> <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> + <string name="handle_text" msgid="4419667835599523257">"Penanganan aplikasi"</string> <string name="app_icon_text" msgid="2823268023931811747">"Ikon Aplikasi"</string> <string name="fullscreen_text" msgid="1162316685217676079">"Layar Penuh"</string> <string name="desktop_text" msgid="1077633567027630454">"Mode Desktop"</string> diff --git a/libs/WindowManager/Shell/res/values-is/strings.xml b/libs/WindowManager/Shell/res/values-is/strings.xml index b955ef89759f..5b1f4d2205f7 100644 --- a/libs/WindowManager/Shell/res/values-is/strings.xml +++ b/libs/WindowManager/Shell/res/values-is/strings.xml @@ -107,7 +107,7 @@ <string name="minimize_button_text" msgid="271592547935841753">"Minnka"</string> <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> + <string name="handle_text" msgid="4419667835599523257">"Handfang forrits"</string> <string name="app_icon_text" msgid="2823268023931811747">"Tákn forrits"</string> <string name="fullscreen_text" msgid="1162316685217676079">"Allur skjárinn"</string> <string name="desktop_text" msgid="1077633567027630454">"Skjáborðsstilling"</string> diff --git a/libs/WindowManager/Shell/res/values-it/strings.xml b/libs/WindowManager/Shell/res/values-it/strings.xml index d33e770f8199..adc9569b0afe 100644 --- a/libs/WindowManager/Shell/res/values-it/strings.xml +++ b/libs/WindowManager/Shell/res/values-it/strings.xml @@ -107,7 +107,7 @@ <string name="minimize_button_text" msgid="271592547935841753">"Riduci a icona"</string> <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> + <string name="handle_text" msgid="4419667835599523257">"Punto di manipolazione app"</string> <string name="app_icon_text" msgid="2823268023931811747">"Icona dell\'app"</string> <string name="fullscreen_text" msgid="1162316685217676079">"Schermo intero"</string> <string name="desktop_text" msgid="1077633567027630454">"Modalità desktop"</string> diff --git a/libs/WindowManager/Shell/res/values-iw/strings.xml b/libs/WindowManager/Shell/res/values-iw/strings.xml index 6ebbc81046bf..9bae1c970b97 100644 --- a/libs/WindowManager/Shell/res/values-iw/strings.xml +++ b/libs/WindowManager/Shell/res/values-iw/strings.xml @@ -107,7 +107,7 @@ <string name="minimize_button_text" msgid="271592547935841753">"מזעור"</string> <string name="close_button_text" msgid="2913281996024033299">"סגירה"</string> <string name="back_button_text" msgid="1469718707134137085">"חזרה"</string> - <string name="handle_text" msgid="1766582106752184456">"נקודת אחיזה"</string> + <string name="handle_text" msgid="4419667835599523257">"נקודת אחיזה לאפליקציה"</string> <string name="app_icon_text" msgid="2823268023931811747">"סמל האפליקציה"</string> <string name="fullscreen_text" msgid="1162316685217676079">"מסך מלא"</string> <string name="desktop_text" msgid="1077633567027630454">"ממשק המחשב"</string> diff --git a/libs/WindowManager/Shell/res/values-ja/strings.xml b/libs/WindowManager/Shell/res/values-ja/strings.xml index 55fd8b16f2a2..fff794eda59b 100644 --- a/libs/WindowManager/Shell/res/values-ja/strings.xml +++ b/libs/WindowManager/Shell/res/values-ja/strings.xml @@ -107,7 +107,7 @@ <string name="minimize_button_text" msgid="271592547935841753">"最小化"</string> <string name="close_button_text" msgid="2913281996024033299">"閉じる"</string> <string name="back_button_text" msgid="1469718707134137085">"戻る"</string> - <string name="handle_text" msgid="1766582106752184456">"ハンドル"</string> + <string name="handle_text" msgid="4419667835599523257">"アプリハンドル"</string> <string name="app_icon_text" msgid="2823268023931811747">"アプリのアイコン"</string> <string name="fullscreen_text" msgid="1162316685217676079">"全画面表示"</string> <string name="desktop_text" msgid="1077633567027630454">"デスクトップ モード"</string> diff --git a/libs/WindowManager/Shell/res/values-ka/strings.xml b/libs/WindowManager/Shell/res/values-ka/strings.xml index 235420812937..a73c4f0f9cff 100644 --- a/libs/WindowManager/Shell/res/values-ka/strings.xml +++ b/libs/WindowManager/Shell/res/values-ka/strings.xml @@ -107,7 +107,7 @@ <string name="minimize_button_text" msgid="271592547935841753">"ჩაკეცვა"</string> <string name="close_button_text" msgid="2913281996024033299">"დახურვა"</string> <string name="back_button_text" msgid="1469718707134137085">"უკან"</string> - <string name="handle_text" msgid="1766582106752184456">"იდენტიფიკატორი"</string> + <string name="handle_text" msgid="4419667835599523257">"აპის იდენტიფიკატორი"</string> <string name="app_icon_text" msgid="2823268023931811747">"აპის ხატულა"</string> <string name="fullscreen_text" msgid="1162316685217676079">"სრულ ეკრანზე"</string> <string name="desktop_text" msgid="1077633567027630454">"დესკტოპის რეჟიმი"</string> diff --git a/libs/WindowManager/Shell/res/values-kk/strings.xml b/libs/WindowManager/Shell/res/values-kk/strings.xml index 3e9b85ecd3a3..5a7197e08942 100644 --- a/libs/WindowManager/Shell/res/values-kk/strings.xml +++ b/libs/WindowManager/Shell/res/values-kk/strings.xml @@ -107,7 +107,7 @@ <string name="minimize_button_text" msgid="271592547935841753">"Кішірейту"</string> <string name="close_button_text" msgid="2913281996024033299">"Жабу"</string> <string name="back_button_text" msgid="1469718707134137085">"Артқа"</string> - <string name="handle_text" msgid="1766582106752184456">"Идентификатор"</string> + <string name="handle_text" msgid="4419667835599523257">"Қолданба идентификаторы"</string> <string name="app_icon_text" msgid="2823268023931811747">"Қолданба белгішесі"</string> <string name="fullscreen_text" msgid="1162316685217676079">"Толық экран"</string> <string name="desktop_text" msgid="1077633567027630454">"Компьютер режимі"</string> diff --git a/libs/WindowManager/Shell/res/values-km/strings.xml b/libs/WindowManager/Shell/res/values-km/strings.xml index 69c0e1eabc05..4db7aeaae457 100644 --- a/libs/WindowManager/Shell/res/values-km/strings.xml +++ b/libs/WindowManager/Shell/res/values-km/strings.xml @@ -107,7 +107,7 @@ <string name="minimize_button_text" msgid="271592547935841753">"បង្រួម"</string> <string name="close_button_text" msgid="2913281996024033299">"បិទ"</string> <string name="back_button_text" msgid="1469718707134137085">"ថយក្រោយ"</string> - <string name="handle_text" msgid="1766582106752184456">"ឈ្មោះអ្នកប្រើប្រាស់"</string> + <string name="handle_text" msgid="4419667835599523257">"ឈ្មោះអ្នកប្រើប្រាស់កម្មវិធី"</string> <string name="app_icon_text" msgid="2823268023931811747">"រូបកម្មវិធី"</string> <string name="fullscreen_text" msgid="1162316685217676079">"អេក្រង់ពេញ"</string> <string name="desktop_text" msgid="1077633567027630454">"មុខងារកុំព្យូទ័រ"</string> diff --git a/libs/WindowManager/Shell/res/values-kn/strings.xml b/libs/WindowManager/Shell/res/values-kn/strings.xml index 88a29df525e9..5615afcf55f8 100644 --- a/libs/WindowManager/Shell/res/values-kn/strings.xml +++ b/libs/WindowManager/Shell/res/values-kn/strings.xml @@ -107,7 +107,7 @@ <string name="minimize_button_text" msgid="271592547935841753">"ಕುಗ್ಗಿಸಿ"</string> <string name="close_button_text" msgid="2913281996024033299">"ಮುಚ್ಚಿರಿ"</string> <string name="back_button_text" msgid="1469718707134137085">"ಹಿಂದಕ್ಕೆ"</string> - <string name="handle_text" msgid="1766582106752184456">"ಹ್ಯಾಂಡಲ್"</string> + <string name="handle_text" msgid="4419667835599523257">"ಆ್ಯಪ್ ಹ್ಯಾಂಡಲ್"</string> <string name="app_icon_text" msgid="2823268023931811747">"ಆ್ಯಪ್ ಐಕಾನ್"</string> <string name="fullscreen_text" msgid="1162316685217676079">"ಫುಲ್ಸ್ಕ್ರೀನ್"</string> <string name="desktop_text" msgid="1077633567027630454">"ಡೆಸ್ಕ್ಟಾಪ್ ಮೋಡ್"</string> diff --git a/libs/WindowManager/Shell/res/values-ko/strings.xml b/libs/WindowManager/Shell/res/values-ko/strings.xml index 0f27080d65cd..33b980d40a6c 100644 --- a/libs/WindowManager/Shell/res/values-ko/strings.xml +++ b/libs/WindowManager/Shell/res/values-ko/strings.xml @@ -107,7 +107,7 @@ <string name="minimize_button_text" msgid="271592547935841753">"최소화"</string> <string name="close_button_text" msgid="2913281996024033299">"닫기"</string> <string name="back_button_text" msgid="1469718707134137085">"뒤로"</string> - <string name="handle_text" msgid="1766582106752184456">"핸들"</string> + <string name="handle_text" msgid="4419667835599523257">"앱 핸들"</string> <string name="app_icon_text" msgid="2823268023931811747">"앱 아이콘"</string> <string name="fullscreen_text" msgid="1162316685217676079">"전체 화면"</string> <string name="desktop_text" msgid="1077633567027630454">"데스크톱 모드"</string> diff --git a/libs/WindowManager/Shell/res/values-ky/strings.xml b/libs/WindowManager/Shell/res/values-ky/strings.xml index 289d930ecedd..bf3ca5255a80 100644 --- a/libs/WindowManager/Shell/res/values-ky/strings.xml +++ b/libs/WindowManager/Shell/res/values-ky/strings.xml @@ -107,7 +107,7 @@ <string name="minimize_button_text" msgid="271592547935841753">"Кичирейтүү"</string> <string name="close_button_text" msgid="2913281996024033299">"Жабуу"</string> <string name="back_button_text" msgid="1469718707134137085">"Артка"</string> - <string name="handle_text" msgid="1766582106752184456">"Маркер"</string> + <string name="handle_text" msgid="4419667835599523257">"Колдонмонун маркери"</string> <string name="app_icon_text" msgid="2823268023931811747">"Колдонмонун сүрөтчөсү"</string> <string name="fullscreen_text" msgid="1162316685217676079">"Толук экран"</string> <string name="desktop_text" msgid="1077633567027630454">"Компьютер режими"</string> diff --git a/libs/WindowManager/Shell/res/values-lo/strings.xml b/libs/WindowManager/Shell/res/values-lo/strings.xml index 0b84d2c45957..ac6fa0085785 100644 --- a/libs/WindowManager/Shell/res/values-lo/strings.xml +++ b/libs/WindowManager/Shell/res/values-lo/strings.xml @@ -107,7 +107,7 @@ <string name="minimize_button_text" msgid="271592547935841753">"ຫຍໍ້ລົງ"</string> <string name="close_button_text" msgid="2913281996024033299">"ປິດ"</string> <string name="back_button_text" msgid="1469718707134137085">"ກັບຄືນ"</string> - <string name="handle_text" msgid="1766582106752184456">"ມືບັງຄັບ"</string> + <string name="handle_text" msgid="4419667835599523257">"ຊື່ຜູ້ໃຊ້ແອັບ"</string> <string name="app_icon_text" msgid="2823268023931811747">"ໄອຄອນແອັບ"</string> <string name="fullscreen_text" msgid="1162316685217676079">"ເຕັມຈໍ"</string> <string name="desktop_text" msgid="1077633567027630454">"ໂໝດເດັສທັອບ"</string> diff --git a/libs/WindowManager/Shell/res/values-lt/strings.xml b/libs/WindowManager/Shell/res/values-lt/strings.xml index 21dbb68c8c04..97b53d343dd8 100644 --- a/libs/WindowManager/Shell/res/values-lt/strings.xml +++ b/libs/WindowManager/Shell/res/values-lt/strings.xml @@ -107,7 +107,7 @@ <string name="minimize_button_text" msgid="271592547935841753">"Sumažinti"</string> <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> + <string name="handle_text" msgid="4419667835599523257">"Programos kreipinys"</string> <string name="app_icon_text" msgid="2823268023931811747">"Programos piktograma"</string> <string name="fullscreen_text" msgid="1162316685217676079">"Visas ekranas"</string> <string name="desktop_text" msgid="1077633567027630454">"Stalinio kompiuterio režimas"</string> diff --git a/libs/WindowManager/Shell/res/values-lv/strings.xml b/libs/WindowManager/Shell/res/values-lv/strings.xml index f988c14605c4..3a7e90a9da21 100644 --- a/libs/WindowManager/Shell/res/values-lv/strings.xml +++ b/libs/WindowManager/Shell/res/values-lv/strings.xml @@ -107,7 +107,7 @@ <string name="minimize_button_text" msgid="271592547935841753">"Minimizēt"</string> <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> + <string name="handle_text" msgid="4419667835599523257">"Lietotnes turis"</string> <string name="app_icon_text" msgid="2823268023931811747">"Lietotnes ikona"</string> <string name="fullscreen_text" msgid="1162316685217676079">"Pilnekrāna režīms"</string> <string name="desktop_text" msgid="1077633567027630454">"Darbvirsmas režīms"</string> diff --git a/libs/WindowManager/Shell/res/values-mk/strings.xml b/libs/WindowManager/Shell/res/values-mk/strings.xml index ce34b9749e80..f7867cecdfae 100644 --- a/libs/WindowManager/Shell/res/values-mk/strings.xml +++ b/libs/WindowManager/Shell/res/values-mk/strings.xml @@ -107,7 +107,7 @@ <string name="minimize_button_text" msgid="271592547935841753">"Минимизирај"</string> <string name="close_button_text" msgid="2913281996024033299">"Затвори"</string> <string name="back_button_text" msgid="1469718707134137085">"Назад"</string> - <string name="handle_text" msgid="1766582106752184456">"Прекар"</string> + <string name="handle_text" msgid="4419667835599523257">"Прекар на апликацијата"</string> <string name="app_icon_text" msgid="2823268023931811747">"Икона на апликацијата"</string> <string name="fullscreen_text" msgid="1162316685217676079">"Цел екран"</string> <string name="desktop_text" msgid="1077633567027630454">"Режим за компјутер"</string> diff --git a/libs/WindowManager/Shell/res/values-ml/strings.xml b/libs/WindowManager/Shell/res/values-ml/strings.xml index 2efd983b3342..68ff07474778 100644 --- a/libs/WindowManager/Shell/res/values-ml/strings.xml +++ b/libs/WindowManager/Shell/res/values-ml/strings.xml @@ -107,7 +107,7 @@ <string name="minimize_button_text" msgid="271592547935841753">"ചെറുതാക്കുക"</string> <string name="close_button_text" msgid="2913281996024033299">"അടയ്ക്കുക"</string> <string name="back_button_text" msgid="1469718707134137085">"മടങ്ങുക"</string> - <string name="handle_text" msgid="1766582106752184456">"ഹാൻഡിൽ"</string> + <string name="handle_text" msgid="4419667835599523257">"ആപ്പ് ഹാൻഡിൽ"</string> <string name="app_icon_text" msgid="2823268023931811747">"ആപ്പ് ഐക്കൺ"</string> <string name="fullscreen_text" msgid="1162316685217676079">"പൂർണ്ണസ്ക്രീൻ"</string> <string name="desktop_text" msgid="1077633567027630454">"ഡെസ്ക്ടോപ്പ് മോഡ്"</string> diff --git a/libs/WindowManager/Shell/res/values-mn/strings.xml b/libs/WindowManager/Shell/res/values-mn/strings.xml index de58ed89864e..27b38bc283f9 100644 --- a/libs/WindowManager/Shell/res/values-mn/strings.xml +++ b/libs/WindowManager/Shell/res/values-mn/strings.xml @@ -107,7 +107,7 @@ <string name="minimize_button_text" msgid="271592547935841753">"Багасгах"</string> <string name="close_button_text" msgid="2913281996024033299">"Хаах"</string> <string name="back_button_text" msgid="1469718707134137085">"Буцах"</string> - <string name="handle_text" msgid="1766582106752184456">"Бариул"</string> + <string name="handle_text" msgid="4419667835599523257">"Аппын бариул"</string> <string name="app_icon_text" msgid="2823268023931811747">"Aппын дүрс тэмдэг"</string> <string name="fullscreen_text" msgid="1162316685217676079">"Бүтэн дэлгэц"</string> <string name="desktop_text" msgid="1077633567027630454">"Дэлгэцийн горим"</string> diff --git a/libs/WindowManager/Shell/res/values-mr/strings.xml b/libs/WindowManager/Shell/res/values-mr/strings.xml index ef71e864a809..f57f06375be9 100644 --- a/libs/WindowManager/Shell/res/values-mr/strings.xml +++ b/libs/WindowManager/Shell/res/values-mr/strings.xml @@ -107,7 +107,7 @@ <string name="minimize_button_text" msgid="271592547935841753">"लहान करा"</string> <string name="close_button_text" msgid="2913281996024033299">"बंद करा"</string> <string name="back_button_text" msgid="1469718707134137085">"मागे जा"</string> - <string name="handle_text" msgid="1766582106752184456">"हँडल"</string> + <string name="handle_text" msgid="4419667835599523257">"अॅपचे हँडल"</string> <string name="app_icon_text" msgid="2823268023931811747">"अॅप आयकन"</string> <string name="fullscreen_text" msgid="1162316685217676079">"फुलस्क्रीन"</string> <string name="desktop_text" msgid="1077633567027630454">"डेस्कटॉप मोड"</string> diff --git a/libs/WindowManager/Shell/res/values-ms/strings.xml b/libs/WindowManager/Shell/res/values-ms/strings.xml index a9a97d8112c6..9c3b8716c7e6 100644 --- a/libs/WindowManager/Shell/res/values-ms/strings.xml +++ b/libs/WindowManager/Shell/res/values-ms/strings.xml @@ -107,7 +107,7 @@ <string name="minimize_button_text" msgid="271592547935841753">"Minimumkan"</string> <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> + <string name="handle_text" msgid="4419667835599523257">"Pengendalian apl"</string> <string name="app_icon_text" msgid="2823268023931811747">"Ikon Apl"</string> <string name="fullscreen_text" msgid="1162316685217676079">"Skrin penuh"</string> <string name="desktop_text" msgid="1077633567027630454">"Mod Desktop"</string> diff --git a/libs/WindowManager/Shell/res/values-my/strings.xml b/libs/WindowManager/Shell/res/values-my/strings.xml index 2f313cfe7e26..2685c56a246c 100644 --- a/libs/WindowManager/Shell/res/values-my/strings.xml +++ b/libs/WindowManager/Shell/res/values-my/strings.xml @@ -107,7 +107,7 @@ <string name="minimize_button_text" msgid="271592547935841753">"ချုံ့ရန်"</string> <string name="close_button_text" msgid="2913281996024033299">"ပိတ်ရန်"</string> <string name="back_button_text" msgid="1469718707134137085">"နောက်သို့"</string> - <string name="handle_text" msgid="1766582106752184456">"သုံးသူအမည်"</string> + <string name="handle_text" msgid="4419667835599523257">"အက်ပ်သုံးသူအမည်"</string> <string name="app_icon_text" msgid="2823268023931811747">"အက်ပ်သင်္ကေတ"</string> <string name="fullscreen_text" msgid="1162316685217676079">"ဖန်သားပြင်အပြည့်"</string> <string name="desktop_text" msgid="1077633567027630454">"ဒက်စ်တော့မုဒ်"</string> diff --git a/libs/WindowManager/Shell/res/values-nb/strings.xml b/libs/WindowManager/Shell/res/values-nb/strings.xml index 11a807b73054..36c0b8b9febd 100644 --- a/libs/WindowManager/Shell/res/values-nb/strings.xml +++ b/libs/WindowManager/Shell/res/values-nb/strings.xml @@ -107,7 +107,7 @@ <string name="minimize_button_text" msgid="271592547935841753">"Minimer"</string> <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> + <string name="handle_text" msgid="4419667835599523257">"Apphåndtak"</string> <string name="app_icon_text" msgid="2823268023931811747">"Appikon"</string> <string name="fullscreen_text" msgid="1162316685217676079">"Fullskjerm"</string> <string name="desktop_text" msgid="1077633567027630454">"Skrivebordmodus"</string> diff --git a/libs/WindowManager/Shell/res/values-ne/strings.xml b/libs/WindowManager/Shell/res/values-ne/strings.xml index 7cc4a437905b..4e96f5f5a0fb 100644 --- a/libs/WindowManager/Shell/res/values-ne/strings.xml +++ b/libs/WindowManager/Shell/res/values-ne/strings.xml @@ -107,7 +107,7 @@ <string name="minimize_button_text" msgid="271592547935841753">"मिनिमाइज गर्नुहोस्"</string> <string name="close_button_text" msgid="2913281996024033299">"बन्द गर्नुहोस्"</string> <string name="back_button_text" msgid="1469718707134137085">"पछाडि"</string> - <string name="handle_text" msgid="1766582106752184456">"ह्यान्डल"</string> + <string name="handle_text" msgid="4419667835599523257">"एपको ह्यान्डल"</string> <string name="app_icon_text" msgid="2823268023931811747">"एपको आइकन"</string> <string name="fullscreen_text" msgid="1162316685217676079">"फुल स्क्रिन"</string> <string name="desktop_text" msgid="1077633567027630454">"डेस्कटप मोड"</string> diff --git a/libs/WindowManager/Shell/res/values-nl/strings.xml b/libs/WindowManager/Shell/res/values-nl/strings.xml index 7480add2ab0a..5ae084a7021a 100644 --- a/libs/WindowManager/Shell/res/values-nl/strings.xml +++ b/libs/WindowManager/Shell/res/values-nl/strings.xml @@ -107,7 +107,7 @@ <string name="minimize_button_text" msgid="271592547935841753">"Minimaliseren"</string> <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> + <string name="handle_text" msgid="4419667835599523257">"App-handgreep"</string> <string name="app_icon_text" msgid="2823268023931811747">"App-icoon"</string> <string name="fullscreen_text" msgid="1162316685217676079">"Volledig scherm"</string> <string name="desktop_text" msgid="1077633567027630454">"Desktopmodus"</string> diff --git a/libs/WindowManager/Shell/res/values-or/strings.xml b/libs/WindowManager/Shell/res/values-or/strings.xml index b3b5e7cd6955..536c6fe18f94 100644 --- a/libs/WindowManager/Shell/res/values-or/strings.xml +++ b/libs/WindowManager/Shell/res/values-or/strings.xml @@ -107,7 +107,7 @@ <string name="minimize_button_text" msgid="271592547935841753">"ଛୋଟ କରନ୍ତୁ"</string> <string name="close_button_text" msgid="2913281996024033299">"ବନ୍ଦ କରନ୍ତୁ"</string> <string name="back_button_text" msgid="1469718707134137085">"ପଛକୁ ଫେରନ୍ତୁ"</string> - <string name="handle_text" msgid="1766582106752184456">"ହେଣ୍ଡେଲ"</string> + <string name="handle_text" msgid="4419667835599523257">"ଆପର ହେଣ୍ଡେଲ"</string> <string name="app_icon_text" msgid="2823268023931811747">"ଆପ ଆଇକନ"</string> <string name="fullscreen_text" msgid="1162316685217676079">"ପୂର୍ଣ୍ଣସ୍କ୍ରିନ"</string> <string name="desktop_text" msgid="1077633567027630454">"ଡେସ୍କଟପ ମୋଡ"</string> diff --git a/libs/WindowManager/Shell/res/values-pa/strings.xml b/libs/WindowManager/Shell/res/values-pa/strings.xml index 4a08f6762673..bdef224e99b4 100644 --- a/libs/WindowManager/Shell/res/values-pa/strings.xml +++ b/libs/WindowManager/Shell/res/values-pa/strings.xml @@ -107,7 +107,7 @@ <string name="minimize_button_text" msgid="271592547935841753">"ਛੋਟਾ ਕਰੋ"</string> <string name="close_button_text" msgid="2913281996024033299">"ਬੰਦ ਕਰੋ"</string> <string name="back_button_text" msgid="1469718707134137085">"ਪਿੱਛੇ"</string> - <string name="handle_text" msgid="1766582106752184456">"ਹੈਂਡਲ"</string> + <string name="handle_text" msgid="4419667835599523257">"ਐਪ ਹੈਂਡਲ"</string> <string name="app_icon_text" msgid="2823268023931811747">"ਐਪ ਪ੍ਰਤੀਕ"</string> <string name="fullscreen_text" msgid="1162316685217676079">"ਪੂਰੀ-ਸਕ੍ਰੀਨ"</string> <string name="desktop_text" msgid="1077633567027630454">"ਡੈਸਕਟਾਪ ਮੋਡ"</string> diff --git a/libs/WindowManager/Shell/res/values-pl/strings.xml b/libs/WindowManager/Shell/res/values-pl/strings.xml index 1c268bd34d55..41c4bb08a29a 100644 --- a/libs/WindowManager/Shell/res/values-pl/strings.xml +++ b/libs/WindowManager/Shell/res/values-pl/strings.xml @@ -107,7 +107,7 @@ <string name="minimize_button_text" msgid="271592547935841753">"Minimalizuj"</string> <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> + <string name="handle_text" msgid="4419667835599523257">"Uchwyt aplikacji"</string> <string name="app_icon_text" msgid="2823268023931811747">"Ikona aplikacji"</string> <string name="fullscreen_text" msgid="1162316685217676079">"Pełny ekran"</string> <string name="desktop_text" msgid="1077633567027630454">"Tryb pulpitu"</string> diff --git a/libs/WindowManager/Shell/res/values-pt-rBR/strings.xml b/libs/WindowManager/Shell/res/values-pt-rBR/strings.xml index 82566fedf890..83d34c04cbfd 100644 --- a/libs/WindowManager/Shell/res/values-pt-rBR/strings.xml +++ b/libs/WindowManager/Shell/res/values-pt-rBR/strings.xml @@ -107,7 +107,7 @@ <string name="minimize_button_text" msgid="271592547935841753">"Minimizar"</string> <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> + <string name="handle_text" msgid="4419667835599523257">"Identificador do app"</string> <string name="app_icon_text" msgid="2823268023931811747">"Ícone do app"</string> <string name="fullscreen_text" msgid="1162316685217676079">"Tela cheia"</string> <string name="desktop_text" msgid="1077633567027630454">"Modo área de trabalho"</string> diff --git a/libs/WindowManager/Shell/res/values-pt-rPT/strings.xml b/libs/WindowManager/Shell/res/values-pt-rPT/strings.xml index b2e89182ace4..425ad052aeca 100644 --- a/libs/WindowManager/Shell/res/values-pt-rPT/strings.xml +++ b/libs/WindowManager/Shell/res/values-pt-rPT/strings.xml @@ -107,7 +107,7 @@ <string name="minimize_button_text" msgid="271592547935841753">"Minimizar"</string> <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="handle_text" msgid="4419667835599523257">"Indicador da app"</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> diff --git a/libs/WindowManager/Shell/res/values-pt/strings.xml b/libs/WindowManager/Shell/res/values-pt/strings.xml index 82566fedf890..83d34c04cbfd 100644 --- a/libs/WindowManager/Shell/res/values-pt/strings.xml +++ b/libs/WindowManager/Shell/res/values-pt/strings.xml @@ -107,7 +107,7 @@ <string name="minimize_button_text" msgid="271592547935841753">"Minimizar"</string> <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> + <string name="handle_text" msgid="4419667835599523257">"Identificador do app"</string> <string name="app_icon_text" msgid="2823268023931811747">"Ícone do app"</string> <string name="fullscreen_text" msgid="1162316685217676079">"Tela cheia"</string> <string name="desktop_text" msgid="1077633567027630454">"Modo área de trabalho"</string> diff --git a/libs/WindowManager/Shell/res/values-ro/strings.xml b/libs/WindowManager/Shell/res/values-ro/strings.xml index 503f68c99c38..ea1a6b7f1422 100644 --- a/libs/WindowManager/Shell/res/values-ro/strings.xml +++ b/libs/WindowManager/Shell/res/values-ro/strings.xml @@ -107,7 +107,7 @@ <string name="minimize_button_text" msgid="271592547935841753">"Minimizează"</string> <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> + <string name="handle_text" msgid="4419667835599523257">"Handle de aplicație"</string> <string name="app_icon_text" msgid="2823268023931811747">"Pictograma aplicației"</string> <string name="fullscreen_text" msgid="1162316685217676079">"Ecran complet"</string> <string name="desktop_text" msgid="1077633567027630454">"Modul desktop"</string> diff --git a/libs/WindowManager/Shell/res/values-ru/strings.xml b/libs/WindowManager/Shell/res/values-ru/strings.xml index b2a60302bd1a..d0292beb27bf 100644 --- a/libs/WindowManager/Shell/res/values-ru/strings.xml +++ b/libs/WindowManager/Shell/res/values-ru/strings.xml @@ -107,7 +107,7 @@ <string name="minimize_button_text" msgid="271592547935841753">"Свернуть"</string> <string name="close_button_text" msgid="2913281996024033299">"Закрыть"</string> <string name="back_button_text" msgid="1469718707134137085">"Назад"</string> - <string name="handle_text" msgid="1766582106752184456">"Маркер"</string> + <string name="handle_text" msgid="4419667835599523257">"Обозначение приложения"</string> <string name="app_icon_text" msgid="2823268023931811747">"Значок приложения"</string> <string name="fullscreen_text" msgid="1162316685217676079">"Полноэкранный режим"</string> <string name="desktop_text" msgid="1077633567027630454">"Режим компьютера"</string> diff --git a/libs/WindowManager/Shell/res/values-si/strings.xml b/libs/WindowManager/Shell/res/values-si/strings.xml index 8589f42dd125..7994222d4913 100644 --- a/libs/WindowManager/Shell/res/values-si/strings.xml +++ b/libs/WindowManager/Shell/res/values-si/strings.xml @@ -107,7 +107,7 @@ <string name="minimize_button_text" msgid="271592547935841753">"කුඩා කරන්න"</string> <string name="close_button_text" msgid="2913281996024033299">"වසන්න"</string> <string name="back_button_text" msgid="1469718707134137085">"ආපසු"</string> - <string name="handle_text" msgid="1766582106752184456">"හැඬලය"</string> + <string name="handle_text" msgid="4419667835599523257">"යෙදුම් හසුරුව"</string> <string name="app_icon_text" msgid="2823268023931811747">"යෙදුම් නිරූපකය"</string> <string name="fullscreen_text" msgid="1162316685217676079">"පූර්ණ තිරය"</string> <string name="desktop_text" msgid="1077633567027630454">"ඩෙස්ක්ටොප් ප්රකාරය"</string> diff --git a/libs/WindowManager/Shell/res/values-sk/strings.xml b/libs/WindowManager/Shell/res/values-sk/strings.xml index 895974462576..896a85b477da 100644 --- a/libs/WindowManager/Shell/res/values-sk/strings.xml +++ b/libs/WindowManager/Shell/res/values-sk/strings.xml @@ -107,7 +107,7 @@ <string name="minimize_button_text" msgid="271592547935841753">"Minimalizovať"</string> <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> + <string name="handle_text" msgid="4419667835599523257">"Rukoväť aplikácie"</string> <string name="app_icon_text" msgid="2823268023931811747">"Ikona aplikácie"</string> <string name="fullscreen_text" msgid="1162316685217676079">"Celá obrazovka"</string> <string name="desktop_text" msgid="1077633567027630454">"Režim počítača"</string> diff --git a/libs/WindowManager/Shell/res/values-sl/strings.xml b/libs/WindowManager/Shell/res/values-sl/strings.xml index 5848f9261d9b..3418c483508d 100644 --- a/libs/WindowManager/Shell/res/values-sl/strings.xml +++ b/libs/WindowManager/Shell/res/values-sl/strings.xml @@ -107,7 +107,7 @@ <string name="minimize_button_text" msgid="271592547935841753">"Minimiraj"</string> <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> + <string name="handle_text" msgid="4419667835599523257">"Identifikator aplikacije"</string> <string name="app_icon_text" msgid="2823268023931811747">"Ikona aplikacije"</string> <string name="fullscreen_text" msgid="1162316685217676079">"Celozaslonsko"</string> <string name="desktop_text" msgid="1077633567027630454">"Namizni način"</string> diff --git a/libs/WindowManager/Shell/res/values-sq/strings.xml b/libs/WindowManager/Shell/res/values-sq/strings.xml index 406389465aa0..306fcaa5191c 100644 --- a/libs/WindowManager/Shell/res/values-sq/strings.xml +++ b/libs/WindowManager/Shell/res/values-sq/strings.xml @@ -107,7 +107,7 @@ <string name="minimize_button_text" msgid="271592547935841753">"Minimizo"</string> <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> + <string name="handle_text" msgid="4419667835599523257">"Emërtimi i aplikacionit"</string> <string name="app_icon_text" msgid="2823268023931811747">"Ikona e aplikacionit"</string> <string name="fullscreen_text" msgid="1162316685217676079">"Ekrani i plotë"</string> <string name="desktop_text" msgid="1077633567027630454">"Modaliteti i desktopit"</string> diff --git a/libs/WindowManager/Shell/res/values-sr/strings.xml b/libs/WindowManager/Shell/res/values-sr/strings.xml index 8402eef99c38..8fd824ec0d1c 100644 --- a/libs/WindowManager/Shell/res/values-sr/strings.xml +++ b/libs/WindowManager/Shell/res/values-sr/strings.xml @@ -107,7 +107,7 @@ <string name="minimize_button_text" msgid="271592547935841753">"Умањите"</string> <string name="close_button_text" msgid="2913281996024033299">"Затворите"</string> <string name="back_button_text" msgid="1469718707134137085">"Назад"</string> - <string name="handle_text" msgid="1766582106752184456">"Идентификатор"</string> + <string name="handle_text" msgid="4419667835599523257">"Идентификатор апликације"</string> <string name="app_icon_text" msgid="2823268023931811747">"Икона апликације"</string> <string name="fullscreen_text" msgid="1162316685217676079">"Преко целог екрана"</string> <string name="desktop_text" msgid="1077633567027630454">"Режим за рачунаре"</string> diff --git a/libs/WindowManager/Shell/res/values-sv/strings.xml b/libs/WindowManager/Shell/res/values-sv/strings.xml index 77c7d09fdb24..b6375c69f0dc 100644 --- a/libs/WindowManager/Shell/res/values-sv/strings.xml +++ b/libs/WindowManager/Shell/res/values-sv/strings.xml @@ -107,7 +107,7 @@ <string name="minimize_button_text" msgid="271592547935841753">"Minimera"</string> <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> + <string name="handle_text" msgid="4419667835599523257">"Apphandtag"</string> <string name="app_icon_text" msgid="2823268023931811747">"Appikon"</string> <string name="fullscreen_text" msgid="1162316685217676079">"Helskärm"</string> <string name="desktop_text" msgid="1077633567027630454">"Datorläge"</string> diff --git a/libs/WindowManager/Shell/res/values-sw/strings.xml b/libs/WindowManager/Shell/res/values-sw/strings.xml index d367c80c7197..2eadf34f5197 100644 --- a/libs/WindowManager/Shell/res/values-sw/strings.xml +++ b/libs/WindowManager/Shell/res/values-sw/strings.xml @@ -107,7 +107,7 @@ <string name="minimize_button_text" msgid="271592547935841753">"Punguza"</string> <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> + <string name="handle_text" msgid="4419667835599523257">"Utambulisho wa programu"</string> <string name="app_icon_text" msgid="2823268023931811747">"Aikoni ya Programu"</string> <string name="fullscreen_text" msgid="1162316685217676079">"Skrini nzima"</string> <string name="desktop_text" msgid="1077633567027630454">"Hali ya Kompyuta ya mezani"</string> diff --git a/libs/WindowManager/Shell/res/values-ta/strings.xml b/libs/WindowManager/Shell/res/values-ta/strings.xml index 697f9519688f..36f69ce02515 100644 --- a/libs/WindowManager/Shell/res/values-ta/strings.xml +++ b/libs/WindowManager/Shell/res/values-ta/strings.xml @@ -107,7 +107,7 @@ <string name="minimize_button_text" msgid="271592547935841753">"சிறிதாக்கும்"</string> <string name="close_button_text" msgid="2913281996024033299">"மூடும்"</string> <string name="back_button_text" msgid="1469718707134137085">"பின்செல்லும்"</string> - <string name="handle_text" msgid="1766582106752184456">"ஹேண்டில்"</string> + <string name="handle_text" msgid="4419667835599523257">"ஆப்ஸ் ஹேண்டில்"</string> <string name="app_icon_text" msgid="2823268023931811747">"ஆப்ஸ் ஐகான்"</string> <string name="fullscreen_text" msgid="1162316685217676079">"முழுத்திரை"</string> <string name="desktop_text" msgid="1077633567027630454">"டெஸ்க்டாப் பயன்முறை"</string> diff --git a/libs/WindowManager/Shell/res/values-te/strings.xml b/libs/WindowManager/Shell/res/values-te/strings.xml index ef094fcc8e64..2446ae8f58e6 100644 --- a/libs/WindowManager/Shell/res/values-te/strings.xml +++ b/libs/WindowManager/Shell/res/values-te/strings.xml @@ -107,7 +107,7 @@ <string name="minimize_button_text" msgid="271592547935841753">"కుదించండి"</string> <string name="close_button_text" msgid="2913281996024033299">"మూసివేయండి"</string> <string name="back_button_text" msgid="1469718707134137085">"వెనుకకు"</string> - <string name="handle_text" msgid="1766582106752184456">"హ్యాండిల్"</string> + <string name="handle_text" msgid="4419667835599523257">"యాప్ హ్యాండిల్"</string> <string name="app_icon_text" msgid="2823268023931811747">"యాప్ చిహ్నం"</string> <string name="fullscreen_text" msgid="1162316685217676079">"ఫుల్-స్క్రీన్"</string> <string name="desktop_text" msgid="1077633567027630454">"డెస్క్టాప్ మోడ్"</string> diff --git a/libs/WindowManager/Shell/res/values-th/strings.xml b/libs/WindowManager/Shell/res/values-th/strings.xml index 762a81a0305a..10cf216064a2 100644 --- a/libs/WindowManager/Shell/res/values-th/strings.xml +++ b/libs/WindowManager/Shell/res/values-th/strings.xml @@ -107,7 +107,7 @@ <string name="minimize_button_text" msgid="271592547935841753">"ย่อ"</string> <string name="close_button_text" msgid="2913281996024033299">"ปิด"</string> <string name="back_button_text" msgid="1469718707134137085">"กลับ"</string> - <string name="handle_text" msgid="1766582106752184456">"แฮนเดิล"</string> + <string name="handle_text" msgid="4419667835599523257">"แฮนเดิลแอป"</string> <string name="app_icon_text" msgid="2823268023931811747">"ไอคอนแอป"</string> <string name="fullscreen_text" msgid="1162316685217676079">"เต็มหน้าจอ"</string> <string name="desktop_text" msgid="1077633567027630454">"โหมดเดสก์ท็อป"</string> diff --git a/libs/WindowManager/Shell/res/values-tl/strings.xml b/libs/WindowManager/Shell/res/values-tl/strings.xml index 418f500aac80..497ac56b408d 100644 --- a/libs/WindowManager/Shell/res/values-tl/strings.xml +++ b/libs/WindowManager/Shell/res/values-tl/strings.xml @@ -107,7 +107,7 @@ <string name="minimize_button_text" msgid="271592547935841753">"I-minimize"</string> <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> + <string name="handle_text" msgid="4419667835599523257">"Handle ng app"</string> <string name="app_icon_text" msgid="2823268023931811747">"Icon ng App"</string> <string name="fullscreen_text" msgid="1162316685217676079">"Fullscreen"</string> <string name="desktop_text" msgid="1077633567027630454">"Desktop Mode"</string> diff --git a/libs/WindowManager/Shell/res/values-tr/strings.xml b/libs/WindowManager/Shell/res/values-tr/strings.xml index 1a9724079e65..05eb1ba79f2a 100644 --- a/libs/WindowManager/Shell/res/values-tr/strings.xml +++ b/libs/WindowManager/Shell/res/values-tr/strings.xml @@ -107,7 +107,7 @@ <string name="minimize_button_text" msgid="271592547935841753">"Küçült"</string> <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> + <string name="handle_text" msgid="4419667835599523257">"Uygulama tanıtıcısı"</string> <string name="app_icon_text" msgid="2823268023931811747">"Uygulama Simgesi"</string> <string name="fullscreen_text" msgid="1162316685217676079">"Tam Ekran"</string> <string name="desktop_text" msgid="1077633567027630454">"Masaüstü Modu"</string> diff --git a/libs/WindowManager/Shell/res/values-uk/strings.xml b/libs/WindowManager/Shell/res/values-uk/strings.xml index a5fcae5775a0..5c3cfaad4b28 100644 --- a/libs/WindowManager/Shell/res/values-uk/strings.xml +++ b/libs/WindowManager/Shell/res/values-uk/strings.xml @@ -107,7 +107,7 @@ <string name="minimize_button_text" msgid="271592547935841753">"Згорнути"</string> <string name="close_button_text" msgid="2913281996024033299">"Закрити"</string> <string name="back_button_text" msgid="1469718707134137085">"Назад"</string> - <string name="handle_text" msgid="1766582106752184456">"Маркер"</string> + <string name="handle_text" msgid="4419667835599523257">"Дескриптор додатка"</string> <string name="app_icon_text" msgid="2823268023931811747">"Значок додатка"</string> <string name="fullscreen_text" msgid="1162316685217676079">"На весь екран"</string> <string name="desktop_text" msgid="1077633567027630454">"Режим комп’ютера"</string> diff --git a/libs/WindowManager/Shell/res/values-ur/strings.xml b/libs/WindowManager/Shell/res/values-ur/strings.xml index 2cf9f325892d..98c433b1159f 100644 --- a/libs/WindowManager/Shell/res/values-ur/strings.xml +++ b/libs/WindowManager/Shell/res/values-ur/strings.xml @@ -107,7 +107,7 @@ <string name="minimize_button_text" msgid="271592547935841753">"چھوٹا کریں"</string> <string name="close_button_text" msgid="2913281996024033299">"بند کریں"</string> <string name="back_button_text" msgid="1469718707134137085">"پیچھے"</string> - <string name="handle_text" msgid="1766582106752184456">"ہینڈل"</string> + <string name="handle_text" msgid="4419667835599523257">"ایپ ہینڈل"</string> <string name="app_icon_text" msgid="2823268023931811747">"ایپ کا آئیکن"</string> <string name="fullscreen_text" msgid="1162316685217676079">"مکمل اسکرین"</string> <string name="desktop_text" msgid="1077633567027630454">"ڈیسک ٹاپ موڈ"</string> diff --git a/libs/WindowManager/Shell/res/values-uz/strings.xml b/libs/WindowManager/Shell/res/values-uz/strings.xml index f8cd43f9d6fa..3ec676d2942d 100644 --- a/libs/WindowManager/Shell/res/values-uz/strings.xml +++ b/libs/WindowManager/Shell/res/values-uz/strings.xml @@ -107,7 +107,7 @@ <string name="minimize_button_text" msgid="271592547935841753">"Kichraytirish"</string> <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> + <string name="handle_text" msgid="4419667835599523257">"Ilova identifikatori"</string> <string name="app_icon_text" msgid="2823268023931811747">"Ilova belgisi"</string> <string name="fullscreen_text" msgid="1162316685217676079">"Butun ekran"</string> <string name="desktop_text" msgid="1077633567027630454">"Desktop rejimi"</string> diff --git a/libs/WindowManager/Shell/res/values-vi/strings.xml b/libs/WindowManager/Shell/res/values-vi/strings.xml index 86e2b3349716..125d703a464e 100644 --- a/libs/WindowManager/Shell/res/values-vi/strings.xml +++ b/libs/WindowManager/Shell/res/values-vi/strings.xml @@ -107,7 +107,7 @@ <string name="minimize_button_text" msgid="271592547935841753">"Thu nhỏ"</string> <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> + <string name="handle_text" msgid="4419667835599523257">"Ô điều khiển ứng dụng"</string> <string name="app_icon_text" msgid="2823268023931811747">"Biểu tượng ứng dụng"</string> <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> diff --git a/libs/WindowManager/Shell/res/values-zh-rCN/strings.xml b/libs/WindowManager/Shell/res/values-zh-rCN/strings.xml index a56553b786c3..6ccc38b624e9 100644 --- a/libs/WindowManager/Shell/res/values-zh-rCN/strings.xml +++ b/libs/WindowManager/Shell/res/values-zh-rCN/strings.xml @@ -107,7 +107,7 @@ <string name="minimize_button_text" msgid="271592547935841753">"最小化"</string> <string name="close_button_text" msgid="2913281996024033299">"关闭"</string> <string name="back_button_text" msgid="1469718707134137085">"返回"</string> - <string name="handle_text" msgid="1766582106752184456">"处理"</string> + <string name="handle_text" msgid="4419667835599523257">"应用手柄"</string> <string name="app_icon_text" msgid="2823268023931811747">"应用图标"</string> <string name="fullscreen_text" msgid="1162316685217676079">"全屏"</string> <string name="desktop_text" msgid="1077633567027630454">"桌面模式"</string> diff --git a/libs/WindowManager/Shell/res/values-zh-rHK/strings.xml b/libs/WindowManager/Shell/res/values-zh-rHK/strings.xml index 78c97e4944c9..2787c1e86b0c 100644 --- a/libs/WindowManager/Shell/res/values-zh-rHK/strings.xml +++ b/libs/WindowManager/Shell/res/values-zh-rHK/strings.xml @@ -107,7 +107,7 @@ <string name="minimize_button_text" msgid="271592547935841753">"最小化"</string> <string name="close_button_text" msgid="2913281996024033299">"關閉"</string> <string name="back_button_text" msgid="1469718707134137085">"返去"</string> - <string name="handle_text" msgid="1766582106752184456">"控點"</string> + <string name="handle_text" msgid="4419667835599523257">"應用程式控點"</string> <string name="app_icon_text" msgid="2823268023931811747">"應用程式圖示"</string> <string name="fullscreen_text" msgid="1162316685217676079">"全螢幕"</string> <string name="desktop_text" msgid="1077633567027630454">"桌面模式"</string> diff --git a/libs/WindowManager/Shell/res/values-zh-rTW/strings.xml b/libs/WindowManager/Shell/res/values-zh-rTW/strings.xml index 307dc9db9381..72050fb3edc6 100644 --- a/libs/WindowManager/Shell/res/values-zh-rTW/strings.xml +++ b/libs/WindowManager/Shell/res/values-zh-rTW/strings.xml @@ -107,7 +107,7 @@ <string name="minimize_button_text" msgid="271592547935841753">"最小化"</string> <string name="close_button_text" msgid="2913281996024033299">"關閉"</string> <string name="back_button_text" msgid="1469718707134137085">"返回"</string> - <string name="handle_text" msgid="1766582106752184456">"控點"</string> + <string name="handle_text" msgid="4419667835599523257">"應用程式控制代碼"</string> <string name="app_icon_text" msgid="2823268023931811747">"應用程式圖示"</string> <string name="fullscreen_text" msgid="1162316685217676079">"全螢幕"</string> <string name="desktop_text" msgid="1077633567027630454">"電腦模式"</string> diff --git a/libs/WindowManager/Shell/res/values-zu/strings.xml b/libs/WindowManager/Shell/res/values-zu/strings.xml index ba3df301df54..ac62a7bd67b2 100644 --- a/libs/WindowManager/Shell/res/values-zu/strings.xml +++ b/libs/WindowManager/Shell/res/values-zu/strings.xml @@ -107,7 +107,7 @@ <string name="minimize_button_text" msgid="271592547935841753">"Nciphisa"</string> <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> + <string name="handle_text" msgid="4419667835599523257">"Inkomba ye-App"</string> <string name="app_icon_text" msgid="2823268023931811747">"Isithonjana Se-app"</string> <string name="fullscreen_text" msgid="1162316685217676079">"Isikrini esigcwele"</string> <string name="desktop_text" msgid="1077633567027630454">"Imodi Yedeskithophu"</string> diff --git a/libs/WindowManager/Shell/res/values/dimen.xml b/libs/WindowManager/Shell/res/values/dimen.xml index 269a58693a24..1eb24580a582 100644 --- a/libs/WindowManager/Shell/res/values/dimen.xml +++ b/libs/WindowManager/Shell/res/values/dimen.xml @@ -296,9 +296,6 @@ <!-- The width of the compat hint. --> <dimen name="compat_hint_width">188dp</dimen> - <!-- The width of the camera compat hint. --> - <dimen name="camera_compat_hint_width">143dp</dimen> - <!-- The corner radius of the letterbox education dialog. --> <dimen name="letterbox_education_dialog_corner_radius">28dp</dimen> @@ -554,15 +551,10 @@ enable_windowing_edge_drag_resize is disabled. --> <dimen name="freeform_resize_corner">44dp</dimen> - <!-- The width of the area at the sides of the screen where a freeform task will transition to - split select if dragged until the touch input is within the range. --> - <dimen name="desktop_mode_transition_area_width">32dp</dimen> - - <!-- The width of the area where a desktop task will transition to fullscreen. --> - <dimen name="desktop_mode_fullscreen_from_desktop_width">80dp</dimen> + <!-- The thickness in dp for all desktop drag transition regions. --> + <dimen name="desktop_mode_transition_region_thickness">44dp</dimen> - <!-- The height of the area where a desktop task will transition to fullscreen. --> - <dimen name="desktop_mode_fullscreen_from_desktop_height">40dp</dimen> + <item type="dimen" format="float" name="desktop_mode_fullscreen_region_scale">0.4</item> <!-- The height on the screen where drag to the left or right edge will result in a desktop task snapping to split size. The empty space between this and the top is to allow diff --git a/libs/WindowManager/Shell/shared/src/com/android/wm/shell/shared/desktopmode/DesktopModeFlags.kt b/libs/WindowManager/Shell/shared/src/com/android/wm/shell/shared/desktopmode/DesktopModeFlags.kt index b1c9a775913a..13049694d3fb 100644 --- a/libs/WindowManager/Shell/shared/src/com/android/wm/shell/shared/desktopmode/DesktopModeFlags.kt +++ b/libs/WindowManager/Shell/shared/src/com/android/wm/shell/shared/desktopmode/DesktopModeFlags.kt @@ -35,6 +35,7 @@ enum class DesktopModeFlags( ) { // All desktop mode related flags will be added here DESKTOP_WINDOWING_MODE(Flags::enableDesktopWindowingMode, true), + CASCADING_WINDOWS(Flags::enableCascadingWindows, true), WALLPAPER_ACTIVITY(Flags::enableDesktopWindowingWallpaperActivity, true), MODALS_POLICY(Flags::enableDesktopWindowingModalsPolicy, true), THEMED_APP_HEADERS(Flags::enableThemedAppHeaders, true), @@ -42,7 +43,8 @@ enum class DesktopModeFlags( APP_HEADER_WITH_TASK_DENSITY(Flags::enableAppHeaderWithTaskDensity, true), TASK_STACK_OBSERVER_IN_SHELL(Flags::enableTaskStackObserverInShell, true), SIZE_CONSTRAINTS(Flags::enableDesktopWindowingSizeConstraints, true), - DYNAMIC_INITIAL_BOUNDS(Flags::enableWindowingDynamicInitialBounds, true); + DYNAMIC_INITIAL_BOUNDS(Flags::enableWindowingDynamicInitialBounds, true), + ENABLE_DESKTOP_WINDOWING_TASK_LIMIT(Flags::enableDesktopWindowingTaskLimit, true); /** * Determines state of flag based on the actual flag and desktop mode developer option overrides. diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/ShellTaskOrganizer.java b/libs/WindowManager/Shell/src/com/android/wm/shell/ShellTaskOrganizer.java index f014e559d4b4..452d12a242c0 100644 --- a/libs/WindowManager/Shell/src/com/android/wm/shell/ShellTaskOrganizer.java +++ b/libs/WindowManager/Shell/src/com/android/wm/shell/ShellTaskOrganizer.java @@ -24,7 +24,6 @@ import static android.app.WindowConfiguration.WINDOWING_MODE_MULTI_WINDOW; import static android.app.WindowConfiguration.WINDOWING_MODE_PINNED; import static android.app.WindowConfiguration.WINDOWING_MODE_UNDEFINED; -import static com.android.wm.shell.compatui.impl.CompatUIEventsKt.CAMERA_CONTROL_STATE_UPDATE; import static com.android.wm.shell.compatui.impl.CompatUIEventsKt.SIZE_COMPAT_RESTART_BUTTON_APPEARED; import static com.android.wm.shell.compatui.impl.CompatUIEventsKt.SIZE_COMPAT_RESTART_BUTTON_CLICKED; import static com.android.wm.shell.protolog.ShellProtoLogGroup.WM_SHELL_TASK_ORG; @@ -61,7 +60,6 @@ import com.android.wm.shell.common.ShellExecutor; import com.android.wm.shell.compatui.CompatUIController; import com.android.wm.shell.compatui.api.CompatUIHandler; import com.android.wm.shell.compatui.api.CompatUIInfo; -import com.android.wm.shell.compatui.impl.CompatUIEvents.CameraControlStateUpdated; import com.android.wm.shell.compatui.impl.CompatUIEvents.SizeCompatRestartButtonAppeared; import com.android.wm.shell.compatui.impl.CompatUIEvents.SizeCompatRestartButtonClicked; import com.android.wm.shell.recents.RecentTasksController; @@ -265,9 +263,6 @@ public class ShellTaskOrganizer extends TaskOrganizer { case SIZE_COMPAT_RESTART_BUTTON_CLICKED: onSizeCompatRestartButtonClicked(compatUIEvent.asType()); break; - case CAMERA_CONTROL_STATE_UPDATE: - onCameraControlStateUpdated(compatUIEvent.asType()); - break; default: } @@ -690,6 +685,15 @@ public class ShellTaskOrganizer extends TaskOrganizer { return result; } + /** Return list of {@link RunningTaskInfo}s on all the displays. */ + public ArrayList<RunningTaskInfo> getRunningTasks() { + ArrayList<RunningTaskInfo> result = new ArrayList<>(); + for (int i = 0; i < mTasks.size(); i++) { + result.add(mTasks.valueAt(i).getTaskInfo()); + } + return result; + } + /** Gets running task by taskId. Returns {@code null} if no such task observed. */ @Nullable public RunningTaskInfo getRunningTaskInfo(int taskId) { @@ -808,21 +812,6 @@ public class ShellTaskOrganizer extends TaskOrganizer { restartTaskTopActivityProcessIfVisible(info.getTaskInfo().token); } - @VisibleForTesting - void onCameraControlStateUpdated(@NonNull CameraControlStateUpdated compatUIEvent) { - final int taskId = compatUIEvent.getTaskId(); - final int state = compatUIEvent.getState(); - final TaskAppearedInfo info; - synchronized (mLock) { - info = mTasks.get(taskId); - } - if (info == null) { - return; - } - updateCameraCompatControlState(info.getTaskInfo().token, state); - } - - private void logSizeCompatRestartButtonEventReported(@NonNull TaskAppearedInfo info, int event) { ActivityInfo topActivityInfo = info.getTaskInfo().topActivityInfo; diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/activityembedding/ActivityEmbeddingAnimationAdapter.java b/libs/WindowManager/Shell/src/com/android/wm/shell/activityembedding/ActivityEmbeddingAnimationAdapter.java index 8d30db64a3e5..86e0f14c5c71 100644 --- a/libs/WindowManager/Shell/src/com/android/wm/shell/activityembedding/ActivityEmbeddingAnimationAdapter.java +++ b/libs/WindowManager/Shell/src/com/android/wm/shell/activityembedding/ActivityEmbeddingAnimationAdapter.java @@ -146,6 +146,11 @@ class ActivityEmbeddingAnimationAdapter { /** To be overridden by subclasses to adjust the animation surface change. */ void onAnimationUpdateInner(@NonNull SurfaceControl.Transaction t) { // Update the surface position and alpha. + if (com.android.graphics.libgui.flags.Flags.edgeExtensionShader() + && mAnimation.getExtensionEdges() != 0) { + t.setEdgeExtensionEffect(mLeash, mAnimation.getExtensionEdges()); + } + mTransformation.getMatrix().postTranslate(mContentRelOffset.x, mContentRelOffset.y); t.setMatrix(mLeash, mTransformation.getMatrix(), mMatrix); t.setAlpha(mLeash, mTransformation.getAlpha()); @@ -165,7 +170,7 @@ class ActivityEmbeddingAnimationAdapter { if (!cropRect.intersect(mWholeAnimationBounds)) { // Hide the surface when it is outside of the animation area. t.setAlpha(mLeash, 0); - } else if (mAnimation.hasExtension()) { + } else if (mAnimation.getExtensionEdges() != 0) { // Allow the surface to be shown in its original bounds in case we want to use edge // extensions. cropRect.union(mContentBounds); @@ -180,6 +185,7 @@ class ActivityEmbeddingAnimationAdapter { @CallSuper void onAnimationEnd(@NonNull SurfaceControl.Transaction t) { onAnimationUpdate(t, mAnimation.getDuration()); + t.setEdgeExtensionEffect(mLeash, /* edge */ 0); } final long getDurationHint() { diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/activityembedding/ActivityEmbeddingAnimationRunner.java b/libs/WindowManager/Shell/src/com/android/wm/shell/activityembedding/ActivityEmbeddingAnimationRunner.java index 5696a544152c..d2cef4baf798 100644 --- a/libs/WindowManager/Shell/src/com/android/wm/shell/activityembedding/ActivityEmbeddingAnimationRunner.java +++ b/libs/WindowManager/Shell/src/com/android/wm/shell/activityembedding/ActivityEmbeddingAnimationRunner.java @@ -144,8 +144,10 @@ class ActivityEmbeddingAnimationRunner { // ending states. prepareForJumpCut(info, startTransaction); } else { - addEdgeExtensionIfNeeded(startTransaction, finishTransaction, - postStartTransactionCallbacks, adapters); + if (!com.android.graphics.libgui.flags.Flags.edgeExtensionShader()) { + addEdgeExtensionIfNeeded(startTransaction, finishTransaction, + postStartTransactionCallbacks, adapters); + } addBackgroundColorIfNeeded(info, startTransaction, finishTransaction, adapters); for (ActivityEmbeddingAnimationAdapter adapter : adapters) { duration = Math.max(duration, adapter.getDurationHint()); @@ -341,7 +343,7 @@ class ActivityEmbeddingAnimationRunner { @NonNull List<ActivityEmbeddingAnimationAdapter> adapters) { for (ActivityEmbeddingAnimationAdapter adapter : adapters) { final Animation animation = adapter.mAnimation; - if (!animation.hasExtension()) { + if (animation.getExtensionEdges() == 0) { continue; } if (adapter.mChange.hasFlags(FLAG_TRANSLUCENT) diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/bubbles/bar/BubbleBarExpandedView.java b/libs/WindowManager/Shell/src/com/android/wm/shell/bubbles/bar/BubbleBarExpandedView.java index 972dce51e02b..24c568c23bf2 100644 --- a/libs/WindowManager/Shell/src/com/android/wm/shell/bubbles/bar/BubbleBarExpandedView.java +++ b/libs/WindowManager/Shell/src/com/android/wm/shell/bubbles/bar/BubbleBarExpandedView.java @@ -169,6 +169,8 @@ public class BubbleBarExpandedView extends FrameLayout implements BubbleTaskView R.layout.bubble_overflow_container, null /* root */); mOverflowView.initialize(expandedViewManager, positioner); addView(mOverflowView); + // Don't show handle for overflow + mHandleView.setVisibility(View.GONE); } else { mTaskView = bubbleTaskView.getTaskView(); mBubbleTaskViewHelper = new BubbleTaskViewHelper(mContext, expandedViewManager, diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/common/DisplayImeController.java b/libs/WindowManager/Shell/src/com/android/wm/shell/common/DisplayImeController.java index 4fbb5744b64b..d7d19f7b8bbd 100644 --- a/libs/WindowManager/Shell/src/com/android/wm/shell/common/DisplayImeController.java +++ b/libs/WindowManager/Shell/src/com/android/wm/shell/common/DisplayImeController.java @@ -315,7 +315,7 @@ public class DisplayImeController implements DisplayController.OnDisplaysChanged } } if (!mImeShowing) { - removeImeSurface(); + removeImeSurface(mDisplayId); } } } else if (!android.view.inputmethod.Flags.refactorInsetsController() @@ -617,7 +617,7 @@ public class DisplayImeController implements DisplayController.OnDisplaysChanged || hasLeash) { t.hide(mImeSourceControl.getLeash()); } - removeImeSurface(); + removeImeSurface(mDisplayId); ImeTracker.forLogging().onHidden(mStatsToken); } else if (mAnimationDirection == DIRECTION_SHOW && !mCancelled) { ImeTracker.forLogging().onShown(mStatsToken); @@ -671,10 +671,10 @@ public class DisplayImeController implements DisplayController.OnDisplaysChanged } } - void removeImeSurface() { + void removeImeSurface(int displayId) { // Remove the IME surface to make the insets invisible for // non-client controlled insets. - InputMethodManagerGlobal.removeImeSurface( + InputMethodManagerGlobal.removeImeSurface(displayId, e -> Slog.e(TAG, "Failed to remove IME surface.", e)); } diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/compatui/CompatUILayout.java b/libs/WindowManager/Shell/src/com/android/wm/shell/compatui/CompatUILayout.java index 2b0bd3272ed2..688f8ca2dc75 100644 --- a/libs/WindowManager/Shell/src/com/android/wm/shell/compatui/CompatUILayout.java +++ b/libs/WindowManager/Shell/src/com/android/wm/shell/compatui/CompatUILayout.java @@ -16,10 +16,7 @@ package com.android.wm.shell.compatui; -import static android.app.CameraCompatTaskInfo.CAMERA_COMPAT_CONTROL_TREATMENT_SUGGESTED; - import android.annotation.IdRes; -import android.app.CameraCompatTaskInfo.CameraCompatControlState; import android.content.Context; import android.util.AttributeSet; import android.view.View; @@ -57,28 +54,10 @@ class CompatUILayout extends LinearLayout { mWindowManager = windowManager; } - void updateCameraTreatmentButton(@CameraCompatControlState int newState) { - int buttonBkgId = newState == CAMERA_COMPAT_CONTROL_TREATMENT_SUGGESTED - ? R.drawable.camera_compat_treatment_suggested_ripple - : R.drawable.camera_compat_treatment_applied_ripple; - int hintStringId = newState == CAMERA_COMPAT_CONTROL_TREATMENT_SUGGESTED - ? R.string.camera_compat_treatment_suggested_button_description - : R.string.camera_compat_treatment_applied_button_description; - final ImageButton button = findViewById(R.id.camera_compat_treatment_button); - button.setImageResource(buttonBkgId); - button.setContentDescription(getResources().getString(hintStringId)); - final LinearLayout hint = findViewById(R.id.camera_compat_hint); - ((TextView) hint.findViewById(R.id.compat_mode_hint_text)).setText(hintStringId); - } - void setSizeCompatHintVisibility(boolean show) { setViewVisibility(R.id.size_compat_hint, show); } - void setCameraCompatHintVisibility(boolean show) { - setViewVisibility(R.id.camera_compat_hint, show); - } - void setRestartButtonVisibility(boolean show) { setViewVisibility(R.id.size_compat_restart_button, show); // Hint should never be visible without button. @@ -87,14 +66,6 @@ class CompatUILayout extends LinearLayout { } } - void setCameraControlVisibility(boolean show) { - setViewVisibility(R.id.camera_compat_control, show); - // Hint should never be visible without button. - if (!show) { - setCameraCompatHintVisibility(/* show= */ false); - } - } - private void setViewVisibility(@IdRes int resId, boolean show) { final View view = findViewById(resId); int visibility = show ? View.VISIBLE : View.GONE; @@ -127,26 +98,5 @@ class CompatUILayout extends LinearLayout { ((TextView) sizeCompatHint.findViewById(R.id.compat_mode_hint_text)) .setText(R.string.restart_button_description); sizeCompatHint.setOnClickListener(view -> setSizeCompatHintVisibility(/* show= */ false)); - - final ImageButton cameraTreatmentButton = - findViewById(R.id.camera_compat_treatment_button); - cameraTreatmentButton.setOnClickListener( - view -> mWindowManager.onCameraTreatmentButtonClicked()); - cameraTreatmentButton.setOnLongClickListener(view -> { - mWindowManager.onCameraButtonLongClicked(); - return true; - }); - - final ImageButton cameraDismissButton = findViewById(R.id.camera_compat_dismiss_button); - cameraDismissButton.setOnClickListener( - view -> mWindowManager.onCameraDismissButtonClicked()); - cameraDismissButton.setOnLongClickListener(view -> { - mWindowManager.onCameraButtonLongClicked(); - return true; - }); - - final LinearLayout cameraCompatHint = findViewById(R.id.camera_compat_hint); - cameraCompatHint.setOnClickListener( - view -> setCameraCompatHintVisibility(/* show= */ false)); } } diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/compatui/CompatUIWindowManager.java b/libs/WindowManager/Shell/src/com/android/wm/shell/compatui/CompatUIWindowManager.java index d289ef239354..271c07d4011d 100644 --- a/libs/WindowManager/Shell/src/com/android/wm/shell/compatui/CompatUIWindowManager.java +++ b/libs/WindowManager/Shell/src/com/android/wm/shell/compatui/CompatUIWindowManager.java @@ -16,10 +16,6 @@ package com.android.wm.shell.compatui; -import static android.app.CameraCompatTaskInfo.CAMERA_COMPAT_CONTROL_DISMISSED; -import static android.app.CameraCompatTaskInfo.CAMERA_COMPAT_CONTROL_HIDDEN; -import static android.app.CameraCompatTaskInfo.CAMERA_COMPAT_CONTROL_TREATMENT_APPLIED; -import static android.app.CameraCompatTaskInfo.CAMERA_COMPAT_CONTROL_TREATMENT_SUGGESTED; import static android.view.WindowManager.LARGE_SCREEN_SMALLEST_SCREEN_WIDTH_DP; import static android.window.TaskConstants.TASK_CHILD_LAYER_COMPAT_UI; @@ -27,11 +23,9 @@ import static com.android.wm.shell.shared.desktopmode.DesktopModeFlags.DESKTOP_W import android.annotation.NonNull; import android.annotation.Nullable; -import android.app.CameraCompatTaskInfo.CameraCompatControlState; import android.app.TaskInfo; import android.content.Context; import android.graphics.Rect; -import android.util.Log; import android.util.Pair; import android.view.LayoutInflater; import android.view.View; @@ -44,7 +38,6 @@ import com.android.wm.shell.common.DisplayLayout; import com.android.wm.shell.common.SyncTransactionQueue; import com.android.wm.shell.compatui.CompatUIController.CompatUIHintsState; import com.android.wm.shell.compatui.api.CompatUIEvent; -import com.android.wm.shell.compatui.impl.CompatUIEvents.CameraControlStateUpdated; import com.android.wm.shell.compatui.impl.CompatUIEvents.SizeCompatRestartButtonAppeared; import com.android.wm.shell.shared.desktopmode.DesktopModeFlags; @@ -69,10 +62,6 @@ class CompatUIWindowManager extends CompatUIWindowManagerAbstract { boolean mHasSizeCompat; @VisibleForTesting - @CameraCompatControlState - int mCameraCompatControlState = CAMERA_COMPAT_CONTROL_HIDDEN; - - @VisibleForTesting @NonNull CompatUIHintsState mCompatUIHintsState; @@ -99,8 +88,6 @@ class CompatUIWindowManager extends CompatUIWindowManagerAbstract { // Don't show the SCM button for freeform tasks mHasSizeCompat &= !taskInfo.isFreeform(); } - mCameraCompatControlState = - taskInfo.appCompatTaskInfo.cameraCompatTaskInfo.cameraCompatControlState; mCompatUIHintsState = compatUIHintsState; mCompatUIConfiguration = compatUIConfiguration; mOnRestartButtonClicked = onRestartButtonClicked; @@ -124,8 +111,7 @@ class CompatUIWindowManager extends CompatUIWindowManagerAbstract { @Override protected boolean eligibleToShowLayout() { - return (mHasSizeCompat && shouldShowSizeCompatRestartButton(getLastTaskInfo())) - || shouldShowCameraControl(); + return mHasSizeCompat && shouldShowSizeCompatRestartButton(getLastTaskInfo()); } @Override @@ -152,22 +138,18 @@ class CompatUIWindowManager extends CompatUIWindowManagerAbstract { public boolean updateCompatInfo(TaskInfo taskInfo, ShellTaskOrganizer.TaskListener taskListener, boolean canShow) { final boolean prevHasSizeCompat = mHasSizeCompat; - final int prevCameraCompatControlState = mCameraCompatControlState; mHasSizeCompat = taskInfo.appCompatTaskInfo.topActivityInSizeCompat; if (DESKTOP_WINDOWING_MODE.isEnabled(mContext) && DesktopModeFlags.DYNAMIC_INITIAL_BOUNDS.isEnabled(mContext)) { // Don't show the SCM button for freeform tasks mHasSizeCompat &= !taskInfo.isFreeform(); } - mCameraCompatControlState = - taskInfo.appCompatTaskInfo.cameraCompatTaskInfo.cameraCompatControlState; if (!super.updateCompatInfo(taskInfo, taskListener, canShow)) { return false; } - if (prevHasSizeCompat != mHasSizeCompat - || prevCameraCompatControlState != mCameraCompatControlState) { + if (prevHasSizeCompat != mHasSizeCompat) { updateVisibilityOfViews(); } @@ -179,34 +161,6 @@ class CompatUIWindowManager extends CompatUIWindowManagerAbstract { mOnRestartButtonClicked.accept(Pair.create(getLastTaskInfo(), getTaskListener())); } - /** Called when the camera treatment button is clicked. */ - void onCameraTreatmentButtonClicked() { - if (!shouldShowCameraControl()) { - Log.w(getTag(), "Camera compat shouldn't receive clicks in the hidden state."); - return; - } - // When a camera control is shown, only two states are allowed: "treament applied" and - // "treatment suggested". Clicks on the conrol's treatment button toggle between these - // two states. - mCameraCompatControlState = - mCameraCompatControlState == CAMERA_COMPAT_CONTROL_TREATMENT_SUGGESTED - ? CAMERA_COMPAT_CONTROL_TREATMENT_APPLIED - : CAMERA_COMPAT_CONTROL_TREATMENT_SUGGESTED; - mCallback.accept(new CameraControlStateUpdated(mTaskId, mCameraCompatControlState)); - mLayout.updateCameraTreatmentButton(mCameraCompatControlState); - } - - /** Called when the camera dismiss button is clicked. */ - void onCameraDismissButtonClicked() { - if (!shouldShowCameraControl()) { - Log.w(getTag(), "Camera compat shouldn't receive clicks in the hidden state."); - return; - } - mCameraCompatControlState = CAMERA_COMPAT_CONTROL_DISMISSED; - mCallback.accept(new CameraControlStateUpdated(mTaskId, CAMERA_COMPAT_CONTROL_DISMISSED)); - mLayout.setCameraControlVisibility(/* show= */ false); - } - /** Called when the restart button is long clicked. */ void onRestartButtonLongClicked() { if (mLayout == null) { @@ -215,14 +169,6 @@ class CompatUIWindowManager extends CompatUIWindowManagerAbstract { mLayout.setSizeCompatHintVisibility(/* show= */ true); } - /** Called when either dismiss or treatment camera buttons is long clicked. */ - void onCameraButtonLongClicked() { - if (mLayout == null) { - return; - } - mLayout.setCameraCompatHintVisibility(/* show= */ true); - } - @Override @VisibleForTesting public void updateSurfacePosition() { @@ -270,6 +216,7 @@ class CompatUIWindowManager extends CompatUIWindowManagerAbstract { return false; } final float percentageAreaOfLetterboxInTask = (float) letterboxArea / taskArea * 100; + return percentageAreaOfLetterboxInTask < mHideScmTolerance; } @@ -284,21 +231,5 @@ class CompatUIWindowManager extends CompatUIWindowManagerAbstract { mLayout.setSizeCompatHintVisibility(/* show= */ true); mCompatUIHintsState.mHasShownSizeCompatHint = true; } - - // Camera control for stretched issues. - mLayout.setCameraControlVisibility(shouldShowCameraControl()); - // Only show by default for the first time. - if (shouldShowCameraControl() && !mCompatUIHintsState.mHasShownCameraCompatHint) { - mLayout.setCameraCompatHintVisibility(/* show= */ true); - mCompatUIHintsState.mHasShownCameraCompatHint = true; - } - if (shouldShowCameraControl()) { - mLayout.updateCameraTreatmentButton(mCameraCompatControlState); - } - } - - private boolean shouldShowCameraControl() { - return mCameraCompatControlState != CAMERA_COMPAT_CONTROL_HIDDEN - && mCameraCompatControlState != CAMERA_COMPAT_CONTROL_DISMISSED; } } diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/compatui/impl/CompatUIEvents.kt b/libs/WindowManager/Shell/src/com/android/wm/shell/compatui/impl/CompatUIEvents.kt index 58ce8ed6c978..23205c3dca9e 100644 --- a/libs/WindowManager/Shell/src/com/android/wm/shell/compatui/impl/CompatUIEvents.kt +++ b/libs/WindowManager/Shell/src/com/android/wm/shell/compatui/impl/CompatUIEvents.kt @@ -16,13 +16,10 @@ package com.android.wm.shell.compatui.impl -import android.app.AppCompatTaskInfo -import android.app.CameraCompatTaskInfo import com.android.wm.shell.compatui.api.CompatUIEvent internal const val SIZE_COMPAT_RESTART_BUTTON_APPEARED = 0 internal const val SIZE_COMPAT_RESTART_BUTTON_CLICKED = 1 -internal const val CAMERA_CONTROL_STATE_UPDATE = 2 /** * All the {@link CompatUIEvent} the Compat UI Framework can handle @@ -35,10 +32,4 @@ sealed class CompatUIEvents(override val eventId: Int) : CompatUIEvent { /** Sent when the size compat restart button is clicked. */ data class SizeCompatRestartButtonClicked(val taskId: Int) : CompatUIEvents(SIZE_COMPAT_RESTART_BUTTON_CLICKED) - - /** Sent when the camera compat control state is updated. */ - data class CameraControlStateUpdated( - val taskId: Int, - @CameraCompatTaskInfo.CameraCompatControlState val state: Int - ) : CompatUIEvents(CAMERA_CONTROL_STATE_UPDATE) }
\ No newline at end of file diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/dagger/WMShellModule.java b/libs/WindowManager/Shell/src/com/android/wm/shell/dagger/WMShellModule.java index afe46f500e51..02625076a7c8 100644 --- a/libs/WindowManager/Shell/src/com/android/wm/shell/dagger/WMShellModule.java +++ b/libs/WindowManager/Shell/src/com/android/wm/shell/dagger/WMShellModule.java @@ -16,7 +16,7 @@ package com.android.wm.shell.dagger; -import static com.android.wm.shell.shared.desktopmode.DesktopModeFlags.DESKTOP_WINDOWING_MODE; +import static com.android.wm.shell.shared.desktopmode.DesktopModeFlags.ENABLE_DESKTOP_WINDOWING_TASK_LIMIT; import android.annotation.Nullable; import android.app.KeyguardManager; @@ -569,7 +569,7 @@ public abstract class WMShellModule { ShellTaskOrganizer shellTaskOrganizer) { int maxTaskLimit = DesktopModeStatus.getMaxTaskLimit(context); if (!DesktopModeStatus.canEnterDesktopMode(context) - || DESKTOP_WINDOWING_MODE.isEnabled(context) + || !ENABLE_DESKTOP_WINDOWING_TASK_LIMIT.isEnabled(context) || maxTaskLimit <= 0) { return Optional.empty(); } diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/dagger/pip/Pip2Module.java b/libs/WindowManager/Shell/src/com/android/wm/shell/dagger/pip/Pip2Module.java index ea7e9685dd92..06c1e68753e1 100644 --- a/libs/WindowManager/Shell/src/com/android/wm/shell/dagger/pip/Pip2Module.java +++ b/libs/WindowManager/Shell/src/com/android/wm/shell/dagger/pip/Pip2Module.java @@ -104,6 +104,7 @@ public abstract class Pip2Module { TaskStackListenerImpl taskStackListener, ShellTaskOrganizer shellTaskOrganizer, PipTransitionState pipTransitionState, + PipTouchHandler pipTouchHandler, @ShellMainThread ShellExecutor mainExecutor) { if (!PipUtils.isPip2ExperimentEnabled()) { return Optional.empty(); @@ -112,7 +113,7 @@ public abstract class Pip2Module { context, shellInit, shellCommandHandler, shellController, displayController, displayInsetsController, pipBoundsState, pipBoundsAlgorithm, pipDisplayLayoutState, pipScheduler, taskStackListener, shellTaskOrganizer, - pipTransitionState, mainExecutor)); + pipTransitionState, pipTouchHandler, mainExecutor)); } } diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/desktopmode/DesktopModeTaskRepository.kt b/libs/WindowManager/Shell/src/com/android/wm/shell/desktopmode/DesktopModeTaskRepository.kt index 4299841da0fa..83752945e9f9 100644 --- a/libs/WindowManager/Shell/src/com/android/wm/shell/desktopmode/DesktopModeTaskRepository.kt +++ b/libs/WindowManager/Shell/src/com/android/wm/shell/desktopmode/DesktopModeTaskRepository.kt @@ -213,7 +213,7 @@ class DesktopModeTaskRepository { * If task was visible on a different display with a different [displayId], removes from * the set of visible tasks on that display and notifies listeners. */ - fun updateVisibleFreeformTasks(displayId: Int, taskId: Int, visible: Boolean) { + fun updateTaskVisibility(displayId: Int, taskId: Int, visible: Boolean) { if (visible) { // If task is visible, remove it from any other display besides [displayId]. removeVisibleTask(taskId, excludedDisplayId = displayId) @@ -250,11 +250,17 @@ class DesktopModeTaskRepository { logD("getVisibleTaskCount=$it") } - /** Adds task (or moves if it already exists) to the top of the ordered list. */ + /** + * Adds task (or moves if it already exists) to the top of the ordered list. + * + * Unminimizes the task if it is minimized. + */ fun addOrMoveFreeformTaskToTop(displayId: Int, taskId: Int) { logD("Add or move task to top: display=%d taskId=%d", taskId, displayId) desktopTaskDataByDisplayId[displayId]?.freeformTasksInZOrder?.remove(taskId) desktopTaskDataByDisplayId.getOrCreate(displayId).freeformTasksInZOrder.add(0, taskId) + // Unminimize the task if it is minimized. + unminimizeTask(displayId, taskId) } /** Minimizes the task for [taskId] and [displayId] */ @@ -270,13 +276,41 @@ class DesktopModeTaskRepository { logW("Unminimize Task: display=%d, task=%d, no task data", displayId, taskId) } - /** Removes task from the ordered list. */ + private fun getDisplayIdForTask(taskId: Int): Int? { + desktopTaskDataByDisplayId.forEach { displayId, data -> + if (taskId in data.freeformTasksInZOrder) { + return displayId + } + } + logW("No display id found for task: taskId=%d", taskId) + return null + } + + /** + * Removes [taskId] from the respective display. If [INVALID_DISPLAY], the original display id + * will be looked up from the task id. + */ fun removeFreeformTask(displayId: Int, taskId: Int) { logD("Removes freeform task: taskId=%d", taskId) + if (displayId == INVALID_DISPLAY) { + // Removes the original display id of the task. + getDisplayIdForTask(taskId)?.let { removeTaskFromDisplay(it, taskId) } + } else { + removeTaskFromDisplay(displayId, taskId) + } + } + + /** Removes given task from a valid [displayId] and updates the repository state. */ + private fun removeTaskFromDisplay(displayId: Int, taskId: Int) { + logD("Removes freeform task: taskId=%d, displayId=%d", taskId, displayId) desktopTaskDataByDisplayId[displayId]?.freeformTasksInZOrder?.remove(taskId) boundsBeforeMaximizeByTaskId.remove(taskId) - logD("Remaining freeform tasks: %d", - desktopTaskDataByDisplayId[displayId]?.freeformTasksInZOrder?.toDumpString() ?: "") + logD("Remaining freeform tasks: %s", + desktopTaskDataByDisplayId[displayId]?.freeformTasksInZOrder?.toDumpString()) + // Remove task from unminimized task if it is minimized. + unminimizeTask(displayId, taskId) + removeActiveTask(taskId) + updateTaskVisibility(displayId, taskId, visible = false); } /** @@ -358,3 +392,4 @@ class DesktopModeTaskRepository { private fun <T> Iterable<T>.toDumpString(): String = joinToString(separator = ", ", prefix = "[", postfix = "]") + diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/desktopmode/DesktopModeUtils.kt b/libs/WindowManager/Shell/src/com/android/wm/shell/desktopmode/DesktopModeUtils.kt index da212e704b24..9fcf73d2c375 100644 --- a/libs/WindowManager/Shell/src/com/android/wm/shell/desktopmode/DesktopModeUtils.kt +++ b/libs/WindowManager/Shell/src/com/android/wm/shell/desktopmode/DesktopModeUtils.kt @@ -52,8 +52,10 @@ fun calculateInitialBounds( val idealSize = calculateIdealSize(screenBounds, scale) // If no top activity exists, apps fullscreen bounds and aspect ratio cannot be calculated. // Instead default to the desired initial bounds. + val stableBounds = Rect() + displayLayout.getStableBoundsForDesktopMode(stableBounds) val topActivityInfo = - taskInfo.topActivityInfo ?: return positionInScreen(idealSize, screenBounds) + taskInfo.topActivityInfo ?: return positionInScreen(idealSize, stableBounds) val initialSize: Size = when (taskInfo.configuration.orientation) { @@ -100,7 +102,7 @@ fun calculateInitialBounds( } } - return positionInScreen(initialSize, screenBounds) + return positionInScreen(initialSize, stableBounds) } /** @@ -163,17 +165,11 @@ private fun calculateIdealSize(screenBounds: Rect, scale: Float): Size { } /** Adjusts bounds to be positioned in the middle of the screen. */ -private fun positionInScreen(desiredSize: Size, screenBounds: Rect): Rect { - // TODO(b/325240051): Position apps with bottom heavy offset - val heightOffset = (screenBounds.height() - desiredSize.height) / 2 - val widthOffset = (screenBounds.width() - desiredSize.width) / 2 - return Rect( - widthOffset, - heightOffset, - desiredSize.width + widthOffset, - desiredSize.height + heightOffset - ) -} +private fun positionInScreen(desiredSize: Size, stableBounds: Rect): Rect = + Rect(0, 0, desiredSize.width, desiredSize.height).apply { + val offset = DesktopTaskPosition.Center.getTopLeftCoordinates(stableBounds, this) + offsetTo(offset.x, offset.y) + } /** * Adjusts bounds to be positioned in the middle of the area provided, not necessarily the diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/desktopmode/DesktopModeVisualIndicator.java b/libs/WindowManager/Shell/src/com/android/wm/shell/desktopmode/DesktopModeVisualIndicator.java index ed0d2b87b03f..6011db7fc752 100644 --- a/libs/WindowManager/Shell/src/com/android/wm/shell/desktopmode/DesktopModeVisualIndicator.java +++ b/libs/WindowManager/Shell/src/com/android/wm/shell/desktopmode/DesktopModeVisualIndicator.java @@ -105,7 +105,7 @@ public class DesktopModeVisualIndicator { // If we are in freeform, we don't want a visible indicator in the "freeform" drag zone. IndicatorType result = IndicatorType.NO_INDICATOR; final int transitionAreaWidth = mContext.getResources().getDimensionPixelSize( - com.android.wm.shell.R.dimen.desktop_mode_transition_area_width); + com.android.wm.shell.R.dimen.desktop_mode_transition_region_thickness); // Because drags in freeform use task position for indicator calculation, we need to // account for the possibility of the task going off the top of the screen by captionHeight final int captionHeight = mContext.getResources().getDimensionPixelSize( @@ -140,18 +140,19 @@ public class DesktopModeVisualIndicator { final Region region = new Region(); int transitionHeight = windowingMode == WINDOWING_MODE_FREEFORM ? mContext.getResources().getDimensionPixelSize( - com.android.wm.shell.R.dimen.desktop_mode_fullscreen_from_desktop_height) + com.android.wm.shell.R.dimen.desktop_mode_transition_region_thickness) : 2 * layout.stableInsets().top; - // A thin, short Rect at the top of the screen. + // A Rect at the top of the screen that takes up the center 40%. if (windowingMode == WINDOWING_MODE_FREEFORM) { - int fromFreeformWidth = mContext.getResources().getDimensionPixelSize( - com.android.wm.shell.R.dimen.desktop_mode_fullscreen_from_desktop_width); - region.union(new Rect((layout.width() / 2) - (fromFreeformWidth / 2), + final float toFullscreenScale = mContext.getResources().getFloat( + R.dimen.desktop_mode_fullscreen_region_scale); + final float toFullscreenWidth = (layout.width() * toFullscreenScale); + region.union(new Rect((int) ((layout.width() / 2f) - (toFullscreenWidth / 2f)), -captionHeight, - (layout.width() / 2) + (fromFreeformWidth / 2), + (int) ((layout.width() / 2f) + (toFullscreenWidth / 2f)), transitionHeight)); } - // A screen-wide, shorter Rect if the task is in fullscreen or split. + // A screen-wide Rect if the task is in fullscreen or split. if (windowingMode == WINDOWING_MODE_FULLSCREEN || windowingMode == WINDOWING_MODE_MULTI_WINDOW) { region.union(new Rect(0, diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/desktopmode/DesktopTaskPosition.kt b/libs/WindowManager/Shell/src/com/android/wm/shell/desktopmode/DesktopTaskPosition.kt new file mode 100644 index 000000000000..97abda81d12d --- /dev/null +++ b/libs/WindowManager/Shell/src/com/android/wm/shell/desktopmode/DesktopTaskPosition.kt @@ -0,0 +1,151 @@ +/* + * Copyright (C) 2024 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.android.wm.shell.desktopmode + +import android.app.TaskInfo +import android.content.res.Resources +import android.graphics.Point +import android.graphics.Rect +import android.view.Gravity +import com.android.internal.annotations.VisibleForTesting +import com.android.wm.shell.desktopmode.DesktopTaskPosition.BottomLeft +import com.android.wm.shell.desktopmode.DesktopTaskPosition.BottomRight +import com.android.wm.shell.desktopmode.DesktopTaskPosition.Center +import com.android.wm.shell.desktopmode.DesktopTaskPosition.TopLeft +import com.android.wm.shell.desktopmode.DesktopTaskPosition.TopRight +import com.android.wm.shell.R + +/** + * The position of a task window in desktop mode. + */ +sealed class DesktopTaskPosition { + data object Center : DesktopTaskPosition() { + private const val WINDOW_HEIGHT_PROPORTION = 0.375 + + override fun getTopLeftCoordinates(frame: Rect, window: Rect): Point { + val x = (frame.width() - window.width()) / 2 + // Position with more margin at the bottom. + val y = (frame.height() - window.height()) * WINDOW_HEIGHT_PROPORTION + frame.top + return Point(x, y.toInt()) + } + + override fun next(): DesktopTaskPosition { + return BottomRight + } + } + + data object BottomRight : DesktopTaskPosition() { + override fun getTopLeftCoordinates(frame: Rect, window: Rect): Point { + return Point(frame.right - window.width(), frame.bottom - window.height()) + } + + override fun next(): DesktopTaskPosition { + return TopLeft + } + } + + data object TopLeft : DesktopTaskPosition() { + override fun getTopLeftCoordinates(frame: Rect, window: Rect): Point { + return Point(frame.left, frame.top) + } + + override fun next(): DesktopTaskPosition { + return BottomLeft + } + } + + data object BottomLeft : DesktopTaskPosition() { + override fun getTopLeftCoordinates(frame: Rect, window: Rect): Point { + return Point(frame.left, frame.bottom - window.height()) + } + + override fun next(): DesktopTaskPosition { + return TopRight + } + } + + data object TopRight : DesktopTaskPosition() { + override fun getTopLeftCoordinates(frame: Rect, window: Rect): Point { + return Point(frame.right - window.width(), frame.top) + } + + override fun next(): DesktopTaskPosition { + return Center + } + } + + /** + * Returns the top left coordinates for the window to be placed in the given + * DesktopTaskPosition in the frame. + */ + abstract fun getTopLeftCoordinates(frame: Rect, window: Rect): Point + + abstract fun next(): DesktopTaskPosition +} + +/** + * If the app has specified horizontal or vertical gravity layout, don't change the + * task position for cascading effect. + */ +fun canChangeTaskPosition(taskInfo: TaskInfo): Boolean { + taskInfo.topActivityInfo?.windowLayout?.let { + val horizontalGravityApplied = it.gravity.and(Gravity.HORIZONTAL_GRAVITY_MASK) + val verticalGravityApplied = it.gravity.and(Gravity.VERTICAL_GRAVITY_MASK) + return horizontalGravityApplied == 0 && verticalGravityApplied == 0 + } + return true +} + +/** + * Returns the current DesktopTaskPosition for a given window in the frame. + */ +@VisibleForTesting(visibility = VisibleForTesting.Visibility.PACKAGE) +fun Rect.getDesktopTaskPosition(bounds: Rect): DesktopTaskPosition { + return when { + top == bounds.top && left == bounds.left -> TopLeft + top == bounds.top && right == bounds.right -> TopRight + bottom == bounds.bottom && left == bounds.left -> BottomLeft + bottom == bounds.bottom && right == bounds.right -> BottomRight + else -> Center + } +} + +internal fun cascadeWindow(res: Resources, frame: Rect, prev: Rect, dest: Rect) { + val candidateBounds = Rect(dest) + val lastPos = frame.getDesktopTaskPosition(prev) + var destCoord = Center.getTopLeftCoordinates(frame, candidateBounds) + candidateBounds.offsetTo(destCoord.x, destCoord.y) + // If the default center position is not free or if last focused window is not at the + // center, get the next cascading window position. + if (!prevBoundsMovedAboveThreshold(res, prev, candidateBounds) || Center != lastPos) { + val nextCascadingPos = lastPos.next() + destCoord = nextCascadingPos.getTopLeftCoordinates(frame, dest) + } + dest.offsetTo(destCoord.x, destCoord.y) +} + +internal fun prevBoundsMovedAboveThreshold(res: Resources, prev: Rect, newBounds: Rect): Boolean { + // This is the required minimum dp for a task to be touchable. + val moveThresholdPx = res.getDimensionPixelSize( + R.dimen.freeform_required_visible_empty_space_in_header) + val leftFar = newBounds.left - prev.left > moveThresholdPx + val topFar = newBounds.top - prev.top > moveThresholdPx + val rightFar = prev.right - newBounds.right > moveThresholdPx + val bottomFar = prev.bottom - newBounds.bottom > moveThresholdPx + + return leftFar || topFar || rightFar || bottomFar +} diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/desktopmode/DesktopTasksController.kt b/libs/WindowManager/Shell/src/com/android/wm/shell/desktopmode/DesktopTasksController.kt index 9d3b2e5d4a32..5f838d3adb3c 100644 --- a/libs/WindowManager/Shell/src/com/android/wm/shell/desktopmode/DesktopTasksController.kt +++ b/libs/WindowManager/Shell/src/com/android/wm/shell/desktopmode/DesktopTasksController.kt @@ -121,7 +121,7 @@ class DesktopTasksController( private val exitDesktopTaskTransitionHandler: ExitDesktopTaskTransitionHandler, private val toggleResizeDesktopTaskTransitionHandler: ToggleResizeDesktopTaskTransitionHandler, private val dragToDesktopTransitionHandler: DragToDesktopTransitionHandler, - private val desktopModeTaskRepository: DesktopModeTaskRepository, + private val taskRepository: DesktopModeTaskRepository, private val desktopModeLoggerTransitionObserver: DesktopModeLoggerTransitionObserver, private val launchAdjacentController: LaunchAdjacentController, private val recentsTransitionHandler: RecentsTransitionHandler, @@ -181,7 +181,7 @@ class DesktopTasksController( } private fun onInit() { - ProtoLog.d(WM_SHELL_DESKTOP_MODE, "Initialize DesktopTasksController") + logD("onInit") shellCommandHandler.addDumpCallback(this::dump, this) shellCommandHandler.addCommandCallback("desktopmode", desktopModeShellCommandHandler, this) shellController.addExternalInterface( @@ -190,16 +190,12 @@ class DesktopTasksController( this ) transitions.addHandler(this) - desktopModeTaskRepository.addVisibleTasksListener(taskVisibilityListener, mainExecutor) + taskRepository.addVisibleTasksListener(taskVisibilityListener, mainExecutor) dragToDesktopTransitionHandler.setDragToDesktopStateListener(dragToDesktopStateListener) recentsTransitionHandler.addTransitionStateListener( object : RecentsTransitionStateListener { override fun onAnimationStateChanged(running: Boolean) { - ProtoLog.v( - WM_SHELL_DESKTOP_MODE, - "DesktopTasksController: recents animation state changed running=%b", - running - ) + logV("Recents animation state changed running=%b", running) recentsAnimationRunning = running } } @@ -227,7 +223,7 @@ class DesktopTasksController( /** Returns the transition type for the given remote transition. */ private fun transitionType(remoteTransition: RemoteTransition?): Int { if (remoteTransition == null) { - ProtoLog.v(WM_SHELL_DESKTOP_MODE, "DesktopTasksController: remoteTransition is null") + logV("RemoteTransition is null") return TRANSIT_NONE } return TRANSIT_TO_FRONT @@ -235,7 +231,7 @@ class DesktopTasksController( /** Show all tasks, that are part of the desktop, on top of launcher */ fun showDesktopApps(displayId: Int, remoteTransition: RemoteTransition? = null) { - ProtoLog.v(WM_SHELL_DESKTOP_MODE, "DesktopTasksController: showDesktopApps") + logV("showDesktopApps") val wct = WindowContainerTransaction() bringDesktopAppsToFront(displayId, wct) @@ -255,7 +251,7 @@ class DesktopTasksController( /** Gets number of visible tasks in [displayId]. */ fun visibleTaskCount(displayId: Int): Int = - desktopModeTaskRepository.getVisibleTaskCount(displayId) + taskRepository.getVisibleTaskCount(displayId) /** Returns true if any tasks are visible in Desktop Mode. */ fun isDesktopModeShowing(displayId: Int): Boolean = visibleTaskCount(displayId) > 0 @@ -286,14 +282,8 @@ class DesktopTasksController( // Fullscreen case where we move the current focused task. moveToDesktop(allFocusedTasks[0].taskId, transitionSource = transitionSource) } - else -> { - ProtoLog.w( - WM_SHELL_DESKTOP_MODE, - "DesktopTasksController: Cannot enter desktop, expected less " + - "than 3 focused tasks but found %d", - allFocusedTasks.size - ) - } + else -> logW("Cannot enter desktop, expected < 3 focused tasks, found %d", + allFocusedTasks.size) } } } @@ -317,11 +307,7 @@ class DesktopTasksController( transitionSource: DesktopModeTransitionSource, ): Boolean { recentTasksController?.findTaskInBackground(taskId)?.let { - ProtoLog.v( - WM_SHELL_DESKTOP_MODE, - "DesktopTasksController: moveToDesktopFromNonRunningTask taskId=%d", - taskId - ) + logV("moveToDesktopFromNonRunningTask with taskId=%d, displayId=%d", taskId) // TODO(342378842): Instead of using default display, support multiple displays val taskToMinimize = bringDesktopAppsToFrontBeforeShowingNewTask(DEFAULT_DISPLAY, wct, taskId) @@ -351,18 +337,10 @@ class DesktopTasksController( ) { if (DesktopModeFlags.MODALS_POLICY.isEnabled(context) && isTopActivityExemptFromDesktopWindowing(context, task)) { - ProtoLog.w( - WM_SHELL_DESKTOP_MODE, - "DesktopTasksController: Cannot enter desktop, " + - "ineligible top activity found." - ) + logW("Cannot enter desktop for taskId %d, ineligible top activity found", task.taskId) return } - ProtoLog.v( - WM_SHELL_DESKTOP_MODE, - "DesktopTasksController: moveToDesktop taskId=%d", - task.taskId - ) + logV("moveToDesktop taskId=%d", task.taskId) exitSplitIfApplicable(wct, task) // Bring other apps to front first val taskToMinimize = @@ -386,11 +364,7 @@ class DesktopTasksController( dragToDesktopValueAnimator: MoveToDesktopAnimator, taskSurface: SurfaceControl, ) { - ProtoLog.v( - WM_SHELL_DESKTOP_MODE, - "DesktopTasksController: startDragToDesktop taskId=%d", - taskInfo.taskId - ) + logV("startDragToDesktop taskId=%d", taskInfo.taskId) interactionJankMonitor.begin(taskSurface, context, CUJ_DESKTOP_MODE_ENTER_APP_HANDLE_DRAG_HOLD) dragToDesktopTransitionHandler.startDragToDesktopTransition( @@ -403,7 +377,7 @@ class DesktopTasksController( * The second part of the animated drag to desktop transition, called after * [startDragToDesktop]. */ - private fun finalizeDragToDesktop(taskInfo: RunningTaskInfo, freeformBounds: Rect) { + private fun finalizeDragToDesktop(taskInfo: RunningTaskInfo) { ProtoLog.v( WM_SHELL_DESKTOP_MODE, "DesktopTasksController: finalizeDragToDesktop taskId=%d", @@ -415,7 +389,6 @@ class DesktopTasksController( val taskToMinimize = bringDesktopAppsToFrontBeforeShowingNewTask(taskInfo.displayId, wct, taskInfo.taskId) addMoveToDesktopChanges(wct, taskInfo) - wct.setBounds(taskInfo.token, freeformBounds) val transition = dragToDesktopTransitionHandler.finishDragToDesktopTransition(wct) transition?.let { addPendingMinimizeTransition(it, taskToMinimize) } } @@ -443,10 +416,10 @@ class DesktopTasksController( * @param taskId task id of the window that's being closed */ fun onDesktopWindowClose(wct: WindowContainerTransaction, displayId: Int, taskId: Int) { - if (desktopModeTaskRepository.isOnlyVisibleNonClosingTask(taskId)) { + if (taskRepository.isOnlyVisibleNonClosingTask(taskId)) { removeWallpaperActivity(wct) } - desktopModeTaskRepository.addClosingTask(displayId, taskId) + taskRepository.addClosingTask(displayId, taskId) } /** Move a task with given `taskId` to fullscreen */ @@ -465,11 +438,7 @@ class DesktopTasksController( /** Move a desktop app to split screen. */ fun moveToSplit(task: RunningTaskInfo) { - ProtoLog.v( - WM_SHELL_DESKTOP_MODE, - "DesktopTasksController: moveToSplit taskId=%d", - task.taskId - ) + logV( "moveToSplit taskId=%s", task.taskId) val wct = WindowContainerTransaction() wct.setBounds(task.token, Rect()) // Rather than set windowing mode to multi-window at task level, set it to @@ -498,11 +467,7 @@ class DesktopTasksController( * [startDragToDesktop]. */ fun cancelDragToDesktop(task: RunningTaskInfo) { - ProtoLog.v( - WM_SHELL_DESKTOP_MODE, - "DesktopTasksController: cancelDragToDesktop taskId=%d", - task.taskId - ) + logV("cancelDragToDesktop taskId=%d", task.taskId) dragToDesktopTransitionHandler.cancelDragToDesktopTransition( DragToDesktopTransitionHandler.CancelState.STANDARD_CANCEL ) @@ -513,11 +478,7 @@ class DesktopTasksController( position: Point, transitionSource: DesktopModeTransitionSource ) { - ProtoLog.v( - WM_SHELL_DESKTOP_MODE, - "DesktopTasksController: moveToFullscreen with animation taskId=%d", - task.taskId - ) + logV("moveToFullscreenWithAnimation taskId=%d", task.taskId) val wct = WindowContainerTransaction() addMoveToFullscreenChanges(wct, task) @@ -541,12 +502,7 @@ class DesktopTasksController( /** Move a task to the front */ fun moveTaskToFront(taskInfo: RunningTaskInfo) { - ProtoLog.v( - WM_SHELL_DESKTOP_MODE, - "DesktopTasksController: moveTaskToFront taskId=%d", - taskInfo.taskId - ) - + logV("moveTaskToFront taskId=%s", taskInfo.taskId) val wct = WindowContainerTransaction() wct.reorder(taskInfo.token, true) val taskToMinimize = addAndGetMinimizeChangesIfNeeded(taskInfo.displayId, wct, taskInfo) @@ -572,15 +528,10 @@ class DesktopTasksController( fun moveToNextDisplay(taskId: Int) { val task = shellTaskOrganizer.getRunningTaskInfo(taskId) if (task == null) { - ProtoLog.w(WM_SHELL_DESKTOP_MODE, "moveToNextDisplay: taskId=%d not found", taskId) + logW("moveToNextDisplay: taskId=%d not found", taskId) return } - ProtoLog.v( - WM_SHELL_DESKTOP_MODE, - "moveToNextDisplay: taskId=%d taskDisplayId=%d", - taskId, - task.displayId - ) + logV("moveToNextDisplay: taskId=%d displayId=%d", taskId, task.displayId) val displayIds = rootTaskDisplayAreaOrganizer.displayIds.sorted() // Get the first display id that is higher than current task display id @@ -590,7 +541,7 @@ class DesktopTasksController( newDisplayId = displayIds.firstOrNull { displayId -> displayId < task.displayId } } if (newDisplayId == null) { - ProtoLog.w(WM_SHELL_DESKTOP_MODE, "moveToNextDisplay: next display not found") + logW("moveToNextDisplay: next display not found") return } moveToDisplay(task, newDisplayId) @@ -602,21 +553,15 @@ class DesktopTasksController( * No-op if task is already on that display per [RunningTaskInfo.displayId]. */ private fun moveToDisplay(task: RunningTaskInfo, displayId: Int) { - ProtoLog.v( - WM_SHELL_DESKTOP_MODE, - "moveToDisplay: taskId=%d displayId=%d", - task.taskId, - displayId - ) - + logV("moveToDisplay: taskId=%d displayId=%d", task.taskId, displayId) if (task.displayId == displayId) { - ProtoLog.d(WM_SHELL_DESKTOP_MODE, "moveToDisplay: task already on display") + logD("moveToDisplay: task already on display %d", displayId) return } val displayAreaInfo = rootTaskDisplayAreaOrganizer.getDisplayAreaInfo(displayId) if (displayAreaInfo == null) { - ProtoLog.w(WM_SHELL_DESKTOP_MODE, "moveToDisplay: display not found") + logW("moveToDisplay: display not found") return } @@ -653,7 +598,7 @@ class DesktopTasksController( // If the task's pre-maximize stable bounds were saved, toggle the task to those bounds. // Otherwise, toggle to the default bounds. val taskBoundsBeforeMaximize = - desktopModeTaskRepository.removeBoundsBeforeMaximize(taskInfo.taskId) + taskRepository.removeBoundsBeforeMaximize(taskInfo.taskId) if (taskBoundsBeforeMaximize != null) { destinationBounds.set(taskBoundsBeforeMaximize) } else { @@ -666,7 +611,7 @@ class DesktopTasksController( } else { // Save current bounds so that task can be restored back to original bounds if necessary // and toggle to the stable bounds. - desktopModeTaskRepository.saveBoundsBeforeMaximize(taskInfo.taskId, currentTaskBounds) + taskRepository.saveBoundsBeforeMaximize(taskInfo.taskId, currentTaskBounds) if (taskInfo.isResizeable) { // if resizable then expand to entire stable bounds (full display minus insets) @@ -771,12 +716,7 @@ class DesktopTasksController( wct: WindowContainerTransaction, newTaskIdInFront: Int? = null ): RunningTaskInfo? { - ProtoLog.v( - WM_SHELL_DESKTOP_MODE, - "DesktopTasksController: bringDesktopAppsToFront, newTaskIdInFront=%s", - newTaskIdInFront ?: "null" - ) - + logV("bringDesktopAppsToFront, newTaskId=%d", newTaskIdInFront) // Move home to front, ensures that we go back home when all desktop windows are closed moveHomeTask(wct, toTop = true) @@ -787,7 +727,7 @@ class DesktopTasksController( } val nonMinimizedTasksOrderedFrontToBack = - desktopModeTaskRepository.getActiveNonMinimizedOrderedTasks(displayId) + taskRepository.getActiveNonMinimizedOrderedTasks(displayId) // If we're adding a new Task we might need to minimize an old one val taskToMinimize: RunningTaskInfo? = if (newTaskIdInFront != null && desktopTasksLimiter.isPresent) { @@ -817,7 +757,7 @@ class DesktopTasksController( } private fun addWallpaperActivity(wct: WindowContainerTransaction) { - ProtoLog.v(WM_SHELL_DESKTOP_MODE, "DesktopTasksController: addWallpaper") + logV("addWallpaperActivity") val intent = Intent(context, DesktopWallpaperActivity::class.java) val options = ActivityOptions.makeBasic().apply { @@ -835,8 +775,8 @@ class DesktopTasksController( } private fun removeWallpaperActivity(wct: WindowContainerTransaction) { - desktopModeTaskRepository.wallpaperActivityToken?.let { token -> - ProtoLog.v(WM_SHELL_DESKTOP_MODE, "DesktopTasksController: removeWallpaper") + taskRepository.wallpaperActivityToken?.let { token -> + logV("removeWallpaperActivity") wct.removeTask(token) } } @@ -874,11 +814,7 @@ class DesktopTasksController( transition: IBinder, request: TransitionRequestInfo ): WindowContainerTransaction? { - ProtoLog.v( - WM_SHELL_DESKTOP_MODE, - "DesktopTasksController: handleRequest request=%s", - request - ) + logV("handleRequest request=%s", request) // Check if we should skip handling this transition var reason = "" val triggerTask = request.triggerTask @@ -916,11 +852,7 @@ class DesktopTasksController( } if (!shouldHandleRequest) { - ProtoLog.v( - WM_SHELL_DESKTOP_MODE, - "DesktopTasksController: skipping handleRequest reason=%s", - reason - ) + logV("skipping handleRequest reason=%s", reason) return null } @@ -940,11 +872,7 @@ class DesktopTasksController( } } } - ProtoLog.v( - WM_SHELL_DESKTOP_MODE, - "DesktopTasksController: handleRequest result=%s", - result ?: "null" - ) + logV("handleRequest result=%s", result) return result } @@ -978,25 +906,20 @@ class DesktopTasksController( task: RunningTaskInfo, transition: IBinder ): WindowContainerTransaction? { - ProtoLog.v(WM_SHELL_DESKTOP_MODE, "DesktopTasksController: handleFreeformTaskLaunch") + logV("handleFreeformTaskLaunch") if (keyguardManager.isKeyguardLocked) { // Do NOT handle freeform task launch when locked. // It will be launched in fullscreen windowing mode (Details: b/160925539) - ProtoLog.v(WM_SHELL_DESKTOP_MODE, "DesktopTasksController: skip keyguard is locked") + logV("skip keyguard is locked") return null } val wct = WindowContainerTransaction() if (!isDesktopModeShowing(task.displayId)) { - ProtoLog.d( - WM_SHELL_DESKTOP_MODE, - "DesktopTasksController: bring desktop tasks to front on transition" + - " taskId=%d", - task.taskId - ) + logD("Bring desktop tasks to front on transition=taskId=%d", task.taskId) // We are outside of desktop mode and already existing desktop task is being launched. // We should make this task go to fullscreen instead of freeform. Note that this means // any re-launch of a freeform window outside of desktop will be in fullscreen. - if (desktopModeTaskRepository.isActiveTask(task.taskId)) { + if (taskRepository.isActiveTask(task.taskId)) { addMoveToFullscreenChanges(wct, task) return wct } @@ -1021,14 +944,9 @@ class DesktopTasksController( task: RunningTaskInfo, transition: IBinder ): WindowContainerTransaction? { - ProtoLog.v(WM_SHELL_DESKTOP_MODE, "DesktopTasksController: handleFullscreenTaskLaunch") + logV("handleFullscreenTaskLaunch") if (isDesktopModeShowing(task.displayId)) { - ProtoLog.d( - WM_SHELL_DESKTOP_MODE, - "DesktopTasksController: switch fullscreen task to freeform on transition" + - " taskId=%d", - task.taskId - ) + logD("Switch fullscreen task to freeform on transition: taskId=%d", task.taskId) return WindowContainerTransaction().also { wct -> addMoveToDesktopChanges(wct, task) // In some launches home task is moved behind new task being launched. Make sure @@ -1055,26 +973,28 @@ class DesktopTasksController( /** Handle task closing by removing wallpaper activity if it's the last active task */ private fun handleTaskClosing(task: RunningTaskInfo): WindowContainerTransaction? { - ProtoLog.v(WM_SHELL_DESKTOP_MODE, "DesktopTasksController: handleTaskClosing") + logV("handleTaskClosing") val wct = WindowContainerTransaction() - if (desktopModeTaskRepository.isOnlyVisibleNonClosingTask(task.taskId) - && desktopModeTaskRepository.wallpaperActivityToken != null) { + if (taskRepository.isOnlyVisibleNonClosingTask(task.taskId) + && taskRepository.wallpaperActivityToken != null) { // Remove wallpaper activity when the last active task is removed removeWallpaperActivity(wct) } - desktopModeTaskRepository.addClosingTask(task.displayId, task.taskId) + taskRepository.addClosingTask(task.displayId, task.taskId) // If a CLOSE or TO_BACK is triggered on a desktop task, remove the task. if (Flags.enableDesktopWindowingBackNavigation() && - desktopModeTaskRepository.isVisibleTask(task.taskId)) { + taskRepository.isVisibleTask(task.taskId)) { wct.removeTask(task.token) } return if (wct.isEmpty) null else wct } - private fun addMoveToDesktopChanges( + @VisibleForTesting + fun addMoveToDesktopChanges( wct: WindowContainerTransaction, taskInfo: RunningTaskInfo ) { + val displayLayout = displayController.getDisplayLayout(taskInfo.displayId) ?: return val tdaInfo = rootTaskDisplayAreaOrganizer.getDisplayAreaInfo(taskInfo.displayId)!! val tdaWindowingMode = tdaInfo.configuration.windowConfiguration.windowingMode val targetWindowingMode = @@ -1084,6 +1004,28 @@ class DesktopTasksController( } else { WINDOWING_MODE_FREEFORM } + val initialBounds = if (DesktopModeFlags.DYNAMIC_INITIAL_BOUNDS.isEnabled(context)) { + calculateInitialBounds(displayLayout, taskInfo) + } else { + getDefaultDesktopTaskBounds(displayLayout) + } + + if (DesktopModeFlags.CASCADING_WINDOWS.isEnabled(context)) { + val stableBounds = Rect() + displayLayout.getStableBoundsForDesktopMode(stableBounds) + + val activeTasks = taskRepository + .getActiveNonMinimizedOrderedTasks(taskInfo.displayId) + activeTasks.firstOrNull()?.let { activeTask -> + shellTaskOrganizer.getRunningTaskInfo(activeTask)?.let { + cascadeWindow(context.resources, stableBounds, + it.configuration.windowConfiguration.bounds, initialBounds) + } + } + } + if (canChangeTaskPosition(taskInfo)) { + wct.setBounds(taskInfo.token, initialBounds) + } wct.setWindowingMode(taskInfo.token, targetWindowingMode) wct.reorder(taskInfo.token, true /* onTop */) if (useDesktopOverrideDensity()) { @@ -1109,7 +1051,7 @@ class DesktopTasksController( if (useDesktopOverrideDensity()) { wct.setDensityDpi(taskInfo.token, getDefaultDensityDpi()) } - if (desktopModeTaskRepository.isOnlyVisibleNonClosingTask(taskInfo.taskId)) { + if (taskRepository.isOnlyVisibleNonClosingTask(taskInfo.taskId)) { // Remove wallpaper activity when leaving desktop mode removeWallpaperActivity(wct) } @@ -1128,7 +1070,7 @@ class DesktopTasksController( // The task's density may have been overridden in freeform; revert it here as we don't // want it overridden in multi-window. wct.setDensityDpi(taskInfo.token, getDefaultDensityDpi()) - if (desktopModeTaskRepository.isOnlyVisibleNonClosingTask(taskInfo.taskId)) { + if (taskRepository.isOnlyVisibleNonClosingTask(taskInfo.taskId)) { // Remove wallpaper activity when leaving desktop mode removeWallpaperActivity(wct) } @@ -1343,16 +1285,10 @@ class DesktopTasksController( val indicatorType = indicator.updateIndicatorType(inputCoordinates, taskInfo.windowingMode) when (indicatorType) { IndicatorType.TO_DESKTOP_INDICATOR -> { - val displayLayout = displayController.getDisplayLayout(taskInfo.displayId) - ?: return IndicatorType.NO_INDICATOR // Start a new jank interaction for the drag release to desktop window animation. interactionJankMonitor.begin(taskSurface, context, CUJ_DESKTOP_MODE_ENTER_APP_HANDLE_DRAG_RELEASE, "to_desktop") - if (DesktopModeFlags.DYNAMIC_INITIAL_BOUNDS.isEnabled(context)) { - finalizeDragToDesktop(taskInfo, calculateInitialBounds(displayLayout, taskInfo)) - } else { - finalizeDragToDesktop(taskInfo, getDefaultDesktopTaskBounds(displayLayout)) - } + finalizeDragToDesktop(taskInfo) } IndicatorType.NO_INDICATOR, IndicatorType.TO_FULLSCREEN_INDICATOR -> { @@ -1370,12 +1306,12 @@ class DesktopTasksController( /** Update the exclusion region for a specified task */ fun onExclusionRegionChanged(taskId: Int, exclusionRegion: Region) { - desktopModeTaskRepository.updateTaskExclusionRegions(taskId, exclusionRegion) + taskRepository.updateTaskExclusionRegions(taskId, exclusionRegion) } /** Remove a previously tracked exclusion region for a specified task. */ fun removeExclusionRegionForTask(taskId: Int) { - desktopModeTaskRepository.removeExclusionRegion(taskId) + taskRepository.removeExclusionRegion(taskId) } /** @@ -1385,7 +1321,7 @@ class DesktopTasksController( * @param callbackExecutor the executor to call the listener on. */ fun addVisibleTasksListener(listener: VisibleTasksListener, callbackExecutor: Executor) { - desktopModeTaskRepository.addVisibleTasksListener(listener, callbackExecutor) + taskRepository.addVisibleTasksListener(listener, callbackExecutor) } /** @@ -1395,7 +1331,7 @@ class DesktopTasksController( * @param callbackExecutor the executor to call the listener on. */ fun setTaskRegionListener(listener: Consumer<Region>, callbackExecutor: Executor) { - desktopModeTaskRepository.setExclusionRegionListener(listener, callbackExecutor) + taskRepository.setExclusionRegionListener(listener, callbackExecutor) } override fun onUnhandledDrag( @@ -1413,7 +1349,7 @@ class DesktopTasksController( if (!multiInstanceHelper.supportsMultiInstanceSplit(launchComponent)) { // TODO(b/320797628): Should only return early if there is an existing running task, and // notify the user as well. But for now, just ignore the drop. - ProtoLog.v(WM_SHELL_DESKTOP_MODE, "Dropped intent does not support multi-instance") + logV("Dropped intent does not support multi-instance") return false } @@ -1445,7 +1381,7 @@ class DesktopTasksController( private fun dump(pw: PrintWriter, prefix: String) { val innerPrefix = "$prefix " pw.println("${prefix}DesktopTasksController") - desktopModeTaskRepository.dump(pw, innerPrefix) + taskRepository.dump(pw, innerPrefix) } /** The interface for calls from outside the shell, within the host process. */ @@ -1520,12 +1456,12 @@ class DesktopTasksController( SingleInstanceRemoteListener<DesktopTasksController, IDesktopTaskListener>( controller, { c -> - c.desktopModeTaskRepository.addVisibleTasksListener( + c.taskRepository.addVisibleTasksListener( listener, c.mainExecutor ) }, - { c -> c.desktopModeTaskRepository.removeVisibleTasksListener(listener) } + { c -> c.taskRepository.removeVisibleTasksListener(listener) } ) } @@ -1552,10 +1488,7 @@ class DesktopTasksController( } override fun hideStashedDesktopApps(displayId: Int) { - ProtoLog.w( - WM_SHELL_DESKTOP_MODE, - "IDesktopModeImpl: hideStashedDesktopApps is deprecated" - ) + ProtoLog.w(WM_SHELL_DESKTOP_MODE, "IDesktopModeImpl: hideStashedDesktopApps is deprecated") } override fun getVisibleTaskCount(displayId: Int): Int { @@ -1579,11 +1512,7 @@ class DesktopTasksController( } override fun setTaskListener(listener: IDesktopTaskListener?) { - ProtoLog.v( - WM_SHELL_DESKTOP_MODE, - "IDesktopModeImpl: set task listener=%s", - listener ?: "null" - ) + ProtoLog.v(WM_SHELL_DESKTOP_MODE, "IDesktopModeImpl: set task listener=%s", listener) executeRemoteCallWithTaskPermission(controller, "setTaskListener") { _ -> listener?.let { remoteListener.register(it) } ?: remoteListener.unregister() } @@ -1596,10 +1525,22 @@ class DesktopTasksController( } } + private fun logV(msg: String, vararg arguments: Any?) { + ProtoLog.v(WM_SHELL_DESKTOP_MODE, "%s: $msg", TAG, *arguments) + } + private fun logD(msg: String, vararg arguments: Any?) { + ProtoLog.d(WM_SHELL_DESKTOP_MODE, "%s: $msg", TAG, *arguments) + } + private fun logW(msg: String, vararg arguments: Any?) { + ProtoLog.w(WM_SHELL_DESKTOP_MODE, "%s: $msg", TAG, *arguments) + } + companion object { @JvmField val DESKTOP_MODE_INITIAL_BOUNDS_SCALE = SystemProperties.getInt("persist.wm.debug.desktop_mode_initial_bounds_scale", 75) / 100f + + private const val TAG = "DesktopTasksController" } /** The positions on a screen that a task can snap to. */ diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/desktopmode/DesktopTasksLimiter.kt b/libs/WindowManager/Shell/src/com/android/wm/shell/desktopmode/DesktopTasksLimiter.kt index a011ff5636d2..f41d6e3f8dc0 100644 --- a/libs/WindowManager/Shell/src/com/android/wm/shell/desktopmode/DesktopTasksLimiter.kt +++ b/libs/WindowManager/Shell/src/com/android/wm/shell/desktopmode/DesktopTasksLimiter.kt @@ -33,7 +33,8 @@ import com.android.wm.shell.transition.Transitions.TransitionObserver * Limits the number of tasks shown in Desktop Mode. * * This class should only be used if - * [com.android.window.flags.Flags.enableDesktopWindowingTaskLimit()] is true. + * [com.android.wm.shell.shared.desktopmode.DesktopModeFlags.ENABLE_DESKTOP_WINDOWING_TASK_LIMIT] + * is enabled and [maxTasksLimit] is strictly greater than 0. */ class DesktopTasksLimiter ( transitions: Transitions, @@ -52,6 +53,8 @@ class DesktopTasksLimiter ( } transitions.registerObserver(minimizeTransitionObserver) taskRepository.addActiveTaskListener(leftoverMinimizedTasksRemover) + ProtoLog.v(ShellProtoLogGroup.WM_SHELL_DESKTOP_MODE, + "DesktopTasksLimiter: starting limiter with a maximum of %d tasks", maxTasksLimit) } private data class TaskDetails (val displayId: Int, val taskId: Int) @@ -86,10 +89,10 @@ class DesktopTasksLimiter ( } /** - * Returns whether the given Task is being reordered to the back in the given transition, or - * is already invisible. + * Returns whether the Task [taskDetails] is being reordered to the back in the transition + * [info], or is already invisible. * - * <p> This check can be used to double-check that a task was indeed minimized before + * This check can be used to double-check that a task was indeed minimized before * marking it as such. */ private fun isTaskReorderedToBackOrInvisible( @@ -138,7 +141,9 @@ class DesktopTasksLimiter ( } ProtoLog.v( ShellProtoLogGroup.WM_SHELL_DESKTOP_MODE, - "DesktopTasksLimiter: removing leftover minimized tasks: $remainingMinimizedTasks") + "DesktopTasksLimiter: removing leftover minimized tasks: %s", + remainingMinimizedTasks, + ) remainingMinimizedTasks.forEach { taskIdToRemove -> val taskToRemove = shellTaskOrganizer.getRunningTaskInfo(taskIdToRemove) if (taskToRemove != null) { @@ -149,8 +154,8 @@ class DesktopTasksLimiter ( } /** - * Mark a task as minimized, this should only be done after the corresponding transition has - * finished so we don't minimize the task if the transition fails. + * Mark [taskId], which must be on [displayId], as minimized, this should only be done after the + * corresponding transition has finished so we don't minimize the task if the transition fails. */ private fun markTaskMinimized(displayId: Int, taskId: Int) { ProtoLog.v( @@ -161,11 +166,9 @@ class DesktopTasksLimiter ( /** * Add a minimize-transition to [wct] if adding [newFrontTaskInfo] brings us over the task - * limit. + * limit, returning the task to minimize. * - * @param transition the transition that the minimize-transition will be appended to, or null if - * the transition will be started later. - * @return the ID of the minimized task, or null if no task is being minimized. + * The task must be on [displayId]. */ fun addAndGetMinimizeTaskChangesIfNeeded( displayId: Int, @@ -220,13 +223,15 @@ class DesktopTasksLimiter ( // No need to minimize anything return null } + val taskIdToMinimize = visibleFreeformTaskIdsOrderedFrontToBack.last() val taskToMinimize = - shellTaskOrganizer.getRunningTaskInfo( - visibleFreeformTaskIdsOrderedFrontToBack.last()) + shellTaskOrganizer.getRunningTaskInfo(taskIdToMinimize) if (taskToMinimize == null) { ProtoLog.e( ShellProtoLogGroup.WM_SHELL_DESKTOP_MODE, - "DesktopTasksLimiter: taskToMinimize == null") + "DesktopTasksLimiter: taskToMinimize(taskId = %d) == null", + taskIdToMinimize, + ) return null } return taskToMinimize diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/freeform/FreeformTaskListener.java b/libs/WindowManager/Shell/src/com/android/wm/shell/freeform/FreeformTaskListener.java index 229d972b2834..456767a1c9af 100644 --- a/libs/WindowManager/Shell/src/com/android/wm/shell/freeform/FreeformTaskListener.java +++ b/libs/WindowManager/Shell/src/com/android/wm/shell/freeform/FreeformTaskListener.java @@ -99,11 +99,10 @@ public class FreeformTaskListener implements ShellTaskOrganizer.TaskListener, if (DesktopModeStatus.canEnterDesktopMode(mContext)) { mDesktopModeTaskRepository.ifPresent(repository -> { repository.addOrMoveFreeformTaskToTop(taskInfo.displayId, taskInfo.taskId); - repository.unminimizeTask(taskInfo.displayId, taskInfo.taskId); if (taskInfo.isVisible) { repository.addActiveTask(taskInfo.displayId, taskInfo.taskId); - repository.updateVisibleFreeformTasks(taskInfo.displayId, taskInfo.taskId, - true); + repository.updateTaskVisibility(taskInfo.displayId, taskInfo.taskId, + /* visible= */ true); } }); } @@ -118,9 +117,6 @@ public class FreeformTaskListener implements ShellTaskOrganizer.TaskListener, if (DesktopModeStatus.canEnterDesktopMode(mContext)) { mDesktopModeTaskRepository.ifPresent(repository -> { repository.removeFreeformTask(taskInfo.displayId, taskInfo.taskId); - repository.unminimizeTask(taskInfo.displayId, taskInfo.taskId); - repository.removeActiveTask(taskInfo.taskId, /* excludedDisplayId= */ null); - repository.updateVisibleFreeformTasks(taskInfo.displayId, taskInfo.taskId, false); }); } mWindowDecorationViewModel.onTaskVanished(taskInfo); @@ -144,7 +140,7 @@ public class FreeformTaskListener implements ShellTaskOrganizer.TaskListener, } else if (repository.isClosingTask(taskInfo.taskId)) { repository.removeClosingTask(taskInfo.taskId); } - repository.updateVisibleFreeformTasks(taskInfo.displayId, taskInfo.taskId, + repository.updateTaskVisibility(taskInfo.displayId, taskInfo.taskId, taskInfo.isVisible); }); } @@ -161,7 +157,6 @@ public class FreeformTaskListener implements ShellTaskOrganizer.TaskListener, if (DesktopModeStatus.canEnterDesktopMode(mContext) && taskInfo.isFocused) { mDesktopModeTaskRepository.ifPresent(repository -> { repository.addOrMoveFreeformTaskToTop(taskInfo.displayId, taskInfo.taskId); - repository.unminimizeTask(taskInfo.displayId, taskInfo.taskId); }); } } diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/pip/phone/PipController.java b/libs/WindowManager/Shell/src/com/android/wm/shell/pip/phone/PipController.java index 7451d2251588..284620e7d0c4 100644 --- a/libs/WindowManager/Shell/src/com/android/wm/shell/pip/phone/PipController.java +++ b/libs/WindowManager/Shell/src/com/android/wm/shell/pip/phone/PipController.java @@ -272,6 +272,7 @@ public class PipController implements PipTransitionController.PipTransitionCallb final boolean changed = onDisplayRotationChanged(mContext, outBounds, currentBounds, mTmpInsetBounds, displayId, fromRotation, toRotation, t); if (changed) { + mMenuController.hideMenu(); // If the pip was in the offset zone earlier, adjust the new bounds to the bottom of the // movement bounds mTouchHandler.adjustBoundsForRotation(outBounds, mPipBoundsState.getBounds(), diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/pip/phone/PipMotionHelper.java b/libs/WindowManager/Shell/src/com/android/wm/shell/pip/phone/PipMotionHelper.java index df3803d54d9d..999ab95ccb1e 100644 --- a/libs/WindowManager/Shell/src/com/android/wm/shell/pip/phone/PipMotionHelper.java +++ b/libs/WindowManager/Shell/src/com/android/wm/shell/pip/phone/PipMotionHelper.java @@ -416,6 +416,17 @@ public class PipMotionHelper implements PipAppOpsListener.Callback, // location now. mSpringingToTouch = false; + // Boost the velocityX if it's zero to forcefully push it towards the nearest edge. + // We don't simply change the xEndValue below since the PhysicsAnimator would rely on the + // same velocityX to find out which edge to snap to. + if (velocityX == 0) { + final int motionCenterX = mPipBoundsState + .getMotionBoundsState().getBoundsInMotion().centerX(); + final int displayCenterX = mPipBoundsState + .getDisplayBounds().centerX(); + velocityX = (motionCenterX < displayCenterX) ? -0.001f : 0.001f; + } + mTemporaryBoundsPhysicsAnimator .spring(FloatProperties.RECT_WIDTH, getBounds().width(), mSpringConfig) .spring(FloatProperties.RECT_HEIGHT, getBounds().height(), mSpringConfig) diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/pip2/phone/PipController.java b/libs/WindowManager/Shell/src/com/android/wm/shell/pip2/phone/PipController.java index 8aa093379ee7..94fe286de869 100644 --- a/libs/WindowManager/Shell/src/com/android/wm/shell/pip2/phone/PipController.java +++ b/libs/WindowManager/Shell/src/com/android/wm/shell/pip2/phone/PipController.java @@ -88,6 +88,7 @@ public class PipController implements ConfigurationChangeListener, private final TaskStackListenerImpl mTaskStackListener; private final ShellTaskOrganizer mShellTaskOrganizer; private final PipTransitionState mPipTransitionState; + private final PipTouchHandler mPipTouchHandler; private final ShellExecutor mMainExecutor; private final PipImpl mImpl; private Consumer<Boolean> mOnIsInPipStateChangedListener; @@ -130,6 +131,7 @@ public class PipController implements ConfigurationChangeListener, TaskStackListenerImpl taskStackListener, ShellTaskOrganizer shellTaskOrganizer, PipTransitionState pipTransitionState, + PipTouchHandler pipTouchHandler, ShellExecutor mainExecutor) { mContext = context; mShellCommandHandler = shellCommandHandler; @@ -144,6 +146,7 @@ public class PipController implements ConfigurationChangeListener, mShellTaskOrganizer = shellTaskOrganizer; mPipTransitionState = pipTransitionState; mPipTransitionState.addPipTransitionStateChangedListener(this); + mPipTouchHandler = pipTouchHandler; mMainExecutor = mainExecutor; mImpl = new PipImpl(); @@ -168,6 +171,7 @@ public class PipController implements ConfigurationChangeListener, TaskStackListenerImpl taskStackListener, ShellTaskOrganizer shellTaskOrganizer, PipTransitionState pipTransitionState, + PipTouchHandler pipTouchHandler, ShellExecutor mainExecutor) { if (!context.getPackageManager().hasSystemFeature(FEATURE_PICTURE_IN_PICTURE)) { ProtoLog.w(ShellProtoLogGroup.WM_SHELL_PICTURE_IN_PICTURE, @@ -177,7 +181,7 @@ public class PipController implements ConfigurationChangeListener, return new PipController(context, shellInit, shellCommandHandler, shellController, displayController, displayInsetsController, pipBoundsState, pipBoundsAlgorithm, pipDisplayLayoutState, pipScheduler, taskStackListener, shellTaskOrganizer, - pipTransitionState, mainExecutor); + pipTransitionState, pipTouchHandler, mainExecutor); } public PipImpl getPipImpl() { @@ -204,7 +208,9 @@ public class PipController implements ConfigurationChangeListener, mDisplayInsetsController.addInsetsChangedListener(mPipDisplayLayoutState.getDisplayId(), new ImeListener(mDisplayController, mPipDisplayLayoutState.getDisplayId()) { @Override - public void onImeVisibilityChanged(boolean imeVisible, int imeHeight) {} + public void onImeVisibilityChanged(boolean imeVisible, int imeHeight) { + mPipTouchHandler.onImeVisibilityChanged(imeVisible, imeHeight); + } }); // Allow other outside processes to bind to PiP controller using the key below. diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/pip2/phone/PipMotionHelper.java b/libs/WindowManager/Shell/src/com/android/wm/shell/pip2/phone/PipMotionHelper.java index ea02de9d9704..83253c6006fb 100644 --- a/libs/WindowManager/Shell/src/com/android/wm/shell/pip2/phone/PipMotionHelper.java +++ b/libs/WindowManager/Shell/src/com/android/wm/shell/pip2/phone/PipMotionHelper.java @@ -134,6 +134,8 @@ public class PipMotionHelper implements PipAppOpsListener.Callback, private final PhysicsAnimator.SpringConfig mConflictResolutionSpringConfig = new PhysicsAnimator.SpringConfig(STIFFNESS_LOW, DAMPING_RATIO_NO_BOUNCY); + @Nullable private Runnable mUpdateMovementBoundsRunnable; + private final Consumer<Rect> mUpdateBoundsCallback = (Rect newBounds) -> { if (mPipBoundsState.getBounds().equals(newBounds)) { return; @@ -141,6 +143,7 @@ public class PipMotionHelper implements PipAppOpsListener.Callback, mMenuController.updateMenuLayout(newBounds); mPipBoundsState.setBounds(newBounds); + maybeUpdateMovementBounds(); }; /** @@ -416,6 +419,17 @@ public class PipMotionHelper implements PipAppOpsListener.Callback, // location now. mSpringingToTouch = false; + // Boost the velocityX if it's zero to forcefully push it towards the nearest edge. + // We don't simply change the xEndValue below since the PhysicsAnimator would rely on the + // same velocityX to find out which edge to snap to. + if (velocityX == 0) { + final int motionCenterX = mPipBoundsState + .getMotionBoundsState().getBoundsInMotion().centerX(); + final int displayCenterX = mPipBoundsState + .getDisplayBounds().centerX(); + velocityX = (motionCenterX < displayCenterX) ? -0.001f : 0.001f; + } + mTemporaryBoundsPhysicsAnimator .spring(FloatProperties.RECT_WIDTH, getBounds().width(), mSpringConfig) .spring(FloatProperties.RECT_HEIGHT, getBounds().height(), mSpringConfig) @@ -555,11 +569,20 @@ public class PipMotionHelper implements PipAppOpsListener.Callback, + " callers=\n%s", TAG, originalBounds, offset, Debug.getCallers(5, " ")); } + if (offset == 0) { + return; + } + cancelPhysicsAnimation(); - /* - mPipTaskOrganizer.scheduleOffsetPip(originalBounds, offset, SHIFT_DURATION, - mUpdateBoundsCallback); - */ + + Rect adjustedBounds = new Rect(originalBounds); + adjustedBounds.offset(0, offset); + + setAnimatingToBounds(adjustedBounds); + Bundle extra = new Bundle(); + extra.putBoolean(ANIMATING_BOUNDS_CHANGE, true); + extra.putInt(ANIMATING_BOUNDS_CHANGE_DURATION, SHIFT_DURATION); + mPipTransitionState.setState(PipTransitionState.SCHEDULED_BOUNDS_CHANGE, extra); } /** @@ -574,11 +597,11 @@ public class PipMotionHelper implements PipAppOpsListener.Callback, /** Set new fling configs whose min/max values respect the given movement bounds. */ private void rebuildFlingConfigs() { mFlingConfigX = new PhysicsAnimator.FlingConfig(DEFAULT_FRICTION, - mPipBoundsAlgorithm.getMovementBounds(getBounds()).left, - mPipBoundsAlgorithm.getMovementBounds(getBounds()).right); + mPipBoundsState.getMovementBounds().left, + mPipBoundsState.getMovementBounds().right); mFlingConfigY = new PhysicsAnimator.FlingConfig(DEFAULT_FRICTION, - mPipBoundsAlgorithm.getMovementBounds(getBounds()).top, - mPipBoundsAlgorithm.getMovementBounds(getBounds()).bottom); + mPipBoundsState.getMovementBounds().top, + mPipBoundsState.getMovementBounds().bottom); final Rect insetBounds = mPipBoundsState.getDisplayLayout().stableInsets(); mStashConfigX = new PhysicsAnimator.FlingConfig( DEFAULT_FRICTION, @@ -660,6 +683,16 @@ public class PipMotionHelper implements PipAppOpsListener.Callback, cleanUpHighPerfSessionMaybe(); } + void setUpdateMovementBoundsRunnable(Runnable updateMovementBoundsRunnable) { + mUpdateMovementBoundsRunnable = updateMovementBoundsRunnable; + } + + private void maybeUpdateMovementBounds() { + if (mUpdateMovementBoundsRunnable != null) { + mUpdateMovementBoundsRunnable.run(); + } + } + /** * Notifies the floating coordinator that we're moving, and sets the animating to bounds so * we return these bounds from @@ -796,8 +829,14 @@ public class PipMotionHelper implements PipAppOpsListener.Callback, startTx, finishTx, mPipBoundsState.getBounds(), mPipBoundsState.getBounds(), destinationBounds, duration, 0f /* angle */); animator.setAnimationEndCallback(() -> { - mPipBoundsState.setBounds(destinationBounds); - // All motion operations have actually finished, so make bounds cache updates. + mUpdateBoundsCallback.accept(destinationBounds); + + // In case an ongoing drag/fling was present before a deterministic resize transition + // kicked in, we need to update the update bounds properly before cleaning in-motion + // state. + mPipBoundsState.getMotionBoundsState().setBoundsInMotion(destinationBounds); + settlePipBoundsAfterPhysicsAnimation(false /* animatingAfter */); + cleanUpHighPerfSessionMaybe(); // Signal that we are done with resize transition mPipScheduler.scheduleFinishResizePip(true /* configAtEnd */); @@ -806,7 +845,7 @@ public class PipMotionHelper implements PipAppOpsListener.Callback, } private void settlePipBoundsAfterPhysicsAnimation(boolean animatingAfter) { - if (!animatingAfter) { + if (!animatingAfter && mPipBoundsState.getMotionBoundsState().isInMotion()) { // The physics animation ended, though we may not necessarily be done animating, such as // when we're still dragging after moving out of the magnetic target. Only set the final // bounds state and clear motion bounds completely if the whole animation is over. diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/pip2/phone/PipResizeGestureHandler.java b/libs/WindowManager/Shell/src/com/android/wm/shell/pip2/phone/PipResizeGestureHandler.java index 5b0ca1837a1c..d28204add0ac 100644 --- a/libs/WindowManager/Shell/src/com/android/wm/shell/pip2/phone/PipResizeGestureHandler.java +++ b/libs/WindowManager/Shell/src/com/android/wm/shell/pip2/phone/PipResizeGestureHandler.java @@ -146,8 +146,8 @@ public class PipResizeGestureHandler implements mUpdateResizeBoundsCallback = (rect) -> { mUserResizeBounds.set(rect); // mMotionHelper.synchronizePinnedStackBounds(); - mUpdateMovementBoundsRunnable.run(); mPipBoundsState.setBounds(rect); + mUpdateMovementBoundsRunnable.run(); resetState(); }; } diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/pip2/phone/PipTouchHandler.java b/libs/WindowManager/Shell/src/com/android/wm/shell/pip2/phone/PipTouchHandler.java index 53b80e8b7542..f387e72b3da6 100644 --- a/libs/WindowManager/Shell/src/com/android/wm/shell/pip2/phone/PipTouchHandler.java +++ b/libs/WindowManager/Shell/src/com/android/wm/shell/pip2/phone/PipTouchHandler.java @@ -199,6 +199,7 @@ public class PipTouchHandler implements PipTransitionState.PipTransitionStateCha mMenuController.addListener(new PipMenuListener()); mGesture = new DefaultPipTouchGesture(); mMotionHelper = pipMotionHelper; + mMotionHelper.setUpdateMovementBoundsRunnable(this::updateMovementBounds); mPipDismissTargetHandler = new PipDismissTargetHandler(context, pipUiEventLogger, mMotionHelper, mainExecutor); mTouchState = new PipTouchState(ViewConfiguration.get(context), @@ -317,6 +318,8 @@ public class PipTouchHandler implements PipTransitionState.PipTransitionStateCha mFloatingContentCoordinator.onContentRemoved(mMotionHelper); mPipResizeGestureHandler.onActivityUnpinned(); mPipInputConsumer.unregisterInputConsumer(); + mPipBoundsState.setHasUserMovedPip(false); + mPipBoundsState.setHasUserResizedPip(false); } void onPinnedStackAnimationEnded( @@ -346,6 +349,22 @@ public class PipTouchHandler implements PipTransitionState.PipTransitionStateCha void onImeVisibilityChanged(boolean imeVisible, int imeHeight) { mIsImeShowing = imeVisible; mImeHeight = imeHeight; + + // Cache new movement bounds using the new potential IME height. + updateMovementBounds(); + + mPipTransitionState.setOnIdlePipTransitionStateRunnable(() -> { + int delta = mPipBoundsState.getMovementBounds().bottom + - mPipBoundsState.getBounds().top; + + boolean hasUserInteracted = (mPipBoundsState.hasUserMovedPip() + || mPipBoundsState.hasUserResizedPip()); + if ((imeVisible && delta < 0) || (!imeVisible && !hasUserInteracted)) { + // The policy is to ignore an IME disappearing if user has interacted with PiP. + // Otherwise, only offset due to an appearing IME if PiP occludes it. + mMotionHelper.animateToOffset(mPipBoundsState.getBounds(), delta); + } + }); } void onShelfVisibilityChanged(boolean shelfVisible, int shelfHeight) { @@ -1077,6 +1096,7 @@ public class PipTouchHandler implements PipTransitionState.PipTransitionStateCha switch (newState) { case PipTransitionState.ENTERED_PIP: onActivityPinned(); + updateMovementBounds(); mTouchState.setAllowInputEvents(true); mTouchState.reset(); break; diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/pip2/phone/PipTransitionState.java b/libs/WindowManager/Shell/src/com/android/wm/shell/pip2/phone/PipTransitionState.java index 29272be6e9bd..a132796f4a84 100644 --- a/libs/WindowManager/Shell/src/com/android/wm/shell/pip2/phone/PipTransitionState.java +++ b/libs/WindowManager/Shell/src/com/android/wm/shell/pip2/phone/PipTransitionState.java @@ -149,6 +149,12 @@ public class PipTransitionState { @Nullable private SurfaceControl mSwipePipToHomeOverlay; + // + // Scheduling-related state + // + @Nullable + private Runnable mOnIdlePipTransitionStateRunnable; + /** * An interface to track state updates as we progress through PiP transitions. */ @@ -197,6 +203,8 @@ public class PipTransitionState { mState = state; dispatchPipTransitionStateChanged(prevState, mState, extra); } + + maybeRunOnIdlePipTransitionStateCallback(); } /** @@ -231,6 +239,29 @@ public class PipTransitionState { } /** + * Schedule a callback to run when in a valid idle PiP state. + * + * <p>We only allow for one callback to be scheduled to avoid cases with multiple transitions + * being scheduled. For instance, if user double taps and IME shows, this would + * schedule a bounds change transition for IME appearing. But if some other transition would + * want to animate PiP before the scheduled callback executes, we would rather want to replace + * the existing callback with a new one, to avoid multiple animations + * as soon as we are idle.</p> + */ + public void setOnIdlePipTransitionStateRunnable( + @Nullable Runnable onIdlePipTransitionStateRunnable) { + mOnIdlePipTransitionStateRunnable = onIdlePipTransitionStateRunnable; + maybeRunOnIdlePipTransitionStateCallback(); + } + + private void maybeRunOnIdlePipTransitionStateCallback() { + if (mOnIdlePipTransitionStateRunnable != null && isPipStateIdle()) { + mOnIdlePipTransitionStateRunnable.run(); + mOnIdlePipTransitionStateRunnable = null; + } + } + + /** * Adds a {@link PipTransitionStateChangedListener} for future PiP transition state updates. */ public void addPipTransitionStateChangedListener(PipTransitionStateChangedListener listener) { @@ -318,6 +349,11 @@ public class PipTransitionState { throw new IllegalStateException("Unknown state: " + state); } + public boolean isPipStateIdle() { + // This needs to be a valid in-PiP state that isn't a transient state. + return mState == ENTERED_PIP || mState == CHANGED_PIP_BOUNDS; + } + @Override public String toString() { return String.format("PipTransitionState(mState=%s, mInSwipePipToHomeTransition=%b)", diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/taskview/TaskViewTransitions.java b/libs/WindowManager/Shell/src/com/android/wm/shell/taskview/TaskViewTransitions.java index e6d1b4593a46..15fe7abb96a5 100644 --- a/libs/WindowManager/Shell/src/com/android/wm/shell/taskview/TaskViewTransitions.java +++ b/libs/WindowManager/Shell/src/com/android/wm/shell/taskview/TaskViewTransitions.java @@ -217,6 +217,11 @@ public class TaskViewTransitions implements Transitions.TransitionHandler { return null; } + /** Returns true if the given {@code taskInfo} belongs to a task view. */ + public boolean isTaskViewTask(ActivityManager.RunningTaskInfo taskInfo) { + return findTaskView(taskInfo) != null; + } + void startTaskView(@NonNull WindowContainerTransaction wct, @NonNull TaskViewTaskController taskView, @NonNull IBinder launchCookie) { updateVisibilityState(taskView, true /* visible */); diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/transition/DefaultTransitionHandler.java b/libs/WindowManager/Shell/src/com/android/wm/shell/transition/DefaultTransitionHandler.java index 778478405dda..d8c8c605184c 100644 --- a/libs/WindowManager/Shell/src/com/android/wm/shell/transition/DefaultTransitionHandler.java +++ b/libs/WindowManager/Shell/src/com/android/wm/shell/transition/DefaultTransitionHandler.java @@ -502,7 +502,8 @@ public class DefaultTransitionHandler implements Transitions.TransitionHandler { backgroundColorForTransition = getTransitionBackgroundColorIfSet(info, change, a, backgroundColorForTransition); - if (!isTask && a.hasExtension()) { + if (!com.android.graphics.libgui.flags.Flags.edgeExtensionShader() && !isTask + && a.getExtensionEdges() != 0) { if (!TransitionUtil.isOpeningType(mode)) { // Can screenshot now (before startTransaction is applied) edgeExtendWindow(change, a, startTransaction, finishTransaction); @@ -512,6 +513,8 @@ public class DefaultTransitionHandler implements Transitions.TransitionHandler { postStartTransactionCallbacks .add(t -> edgeExtendWindow(change, a, t, finishTransaction)); } + } else if (com.android.graphics.libgui.flags.Flags.edgeExtensionShader()) { + finishTransaction.setEdgeExtensionEffect(change.getLeash(), /* edge */ 0); } final Rect clipRect = TransitionUtil.isClosingType(mode) @@ -1008,6 +1011,10 @@ public class DefaultTransitionHandler implements Transitions.TransitionHandler { Point position, float cornerRadius, @Nullable Rect immutableClipRect) { tmpTransformation.clear(); anim.getTransformation(time, tmpTransformation); + if (anim.getExtensionEdges() != 0 + && com.android.graphics.libgui.flags.Flags.edgeExtensionShader()) { + t.setEdgeExtensionEffect(leash, anim.getExtensionEdges()); + } if (position != null) { tmpTransformation.getMatrix().postTranslate(position.x, position.y); } diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/windowdecor/CaptionWindowDecorViewModel.java b/libs/WindowManager/Shell/src/com/android/wm/shell/windowdecor/CaptionWindowDecorViewModel.java index 5c230c0a505c..d8dba71c0a4f 100644 --- a/libs/WindowManager/Shell/src/com/android/wm/shell/windowdecor/CaptionWindowDecorViewModel.java +++ b/libs/WindowManager/Shell/src/com/android/wm/shell/windowdecor/CaptionWindowDecorViewModel.java @@ -33,6 +33,7 @@ import android.graphics.Region; import android.hardware.input.InputManager; import android.os.Handler; import android.os.RemoteException; +import android.os.UserHandle; import android.provider.Settings; import android.util.Log; import android.util.SparseArray; @@ -288,6 +289,7 @@ public class CaptionWindowDecorViewModel implements WindowDecorViewModel { final CaptionWindowDecoration windowDecoration = new CaptionWindowDecoration( mContext, + mContext.createContextAsUser(UserHandle.of(taskInfo.userId), 0 /* flags */), mDisplayController, mTaskOrganizer, taskInfo, diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/windowdecor/CaptionWindowDecoration.java b/libs/WindowManager/Shell/src/com/android/wm/shell/windowdecor/CaptionWindowDecoration.java index cf42a49f7103..de514f661d01 100644 --- a/libs/WindowManager/Shell/src/com/android/wm/shell/windowdecor/CaptionWindowDecoration.java +++ b/libs/WindowManager/Shell/src/com/android/wm/shell/windowdecor/CaptionWindowDecoration.java @@ -77,6 +77,7 @@ public class CaptionWindowDecoration extends WindowDecoration<WindowDecorLinearL CaptionWindowDecoration( Context context, + @NonNull Context userContext, DisplayController displayController, ShellTaskOrganizer taskOrganizer, RunningTaskInfo taskInfo, @@ -85,7 +86,7 @@ public class CaptionWindowDecoration extends WindowDecoration<WindowDecorLinearL @ShellBackgroundThread ShellExecutor bgExecutor, Choreographer choreographer, SyncTransactionQueue syncQueue) { - super(context, displayController, taskOrganizer, taskInfo, taskSurface); + super(context, userContext, displayController, taskOrganizer, taskInfo, taskSurface); mHandler = handler; mBgExecutor = bgExecutor; mChoreographer = choreographer; 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 0ff35226b77e..7c8f205ce78f 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 @@ -59,6 +59,7 @@ import android.net.Uri; import android.os.Handler; import android.os.Looper; import android.os.RemoteException; +import android.os.UserHandle; import android.util.Log; import android.util.SparseArray; import android.view.Choreographer; @@ -1149,6 +1150,7 @@ public class DesktopModeWindowDecorViewModel implements WindowDecorViewModel { final DesktopModeWindowDecoration windowDecoration = mDesktopModeWindowDecorFactory.create( mContext, + mContext.createContextAsUser(UserHandle.of(taskInfo.userId), 0 /* flags */), mDisplayController, mSplitScreenController, mTaskOrganizer, diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/windowdecor/DesktopModeWindowDecoration.java b/libs/WindowManager/Shell/src/com/android/wm/shell/windowdecor/DesktopModeWindowDecoration.java index 41f428b6ca83..e82990f9fe1d 100644 --- a/libs/WindowManager/Shell/src/com/android/wm/shell/windowdecor/DesktopModeWindowDecoration.java +++ b/libs/WindowManager/Shell/src/com/android/wm/shell/windowdecor/DesktopModeWindowDecoration.java @@ -160,6 +160,7 @@ public class DesktopModeWindowDecoration extends WindowDecoration<WindowDecorLin DesktopModeWindowDecoration( Context context, + @NonNull Context userContext, DisplayController displayController, SplitScreenController splitScreenController, ShellTaskOrganizer taskOrganizer, @@ -171,8 +172,8 @@ public class DesktopModeWindowDecoration extends WindowDecoration<WindowDecorLin SyncTransactionQueue syncQueue, RootTaskDisplayAreaOrganizer rootTaskDisplayAreaOrganizer, AppToWebGenericLinksParser genericLinksParser) { - this (context, displayController, splitScreenController, taskOrganizer, taskInfo, - taskSurface, handler, bgExecutor, choreographer, syncQueue, + this (context, userContext, displayController, splitScreenController, taskOrganizer, + taskInfo, taskSurface, handler, bgExecutor, choreographer, syncQueue, rootTaskDisplayAreaOrganizer, genericLinksParser, SurfaceControl.Builder::new, SurfaceControl.Transaction::new, WindowContainerTransaction::new, SurfaceControl::new, new SurfaceControlViewHostFactory() {}, @@ -181,6 +182,7 @@ public class DesktopModeWindowDecoration extends WindowDecoration<WindowDecorLin DesktopModeWindowDecoration( Context context, + @NonNull Context userContext, DisplayController displayController, SplitScreenController splitScreenController, ShellTaskOrganizer taskOrganizer, @@ -199,7 +201,7 @@ public class DesktopModeWindowDecoration extends WindowDecoration<WindowDecorLin SurfaceControlViewHostFactory surfaceControlViewHostFactory, MaximizeMenuFactory maximizeMenuFactory, HandleMenuFactory handleMenuFactory) { - super(context, displayController, taskOrganizer, taskInfo, taskSurface, + super(context, userContext, displayController, taskOrganizer, taskInfo, taskSurface, surfaceControlBuilderSupplier, surfaceControlTransactionSupplier, windowContainerTransactionSupplier, surfaceControlSupplier, surfaceControlViewHostFactory); @@ -737,12 +739,8 @@ public class DesktopModeWindowDecoration extends WindowDecoration<WindowDecorLin Slog.e(TAG, "Base activity component not found in task"); return; } - final PackageManager pm = mContext.getApplicationContext().getPackageManager(); - final ActivityInfo activityInfo = pm.getActivityInfo(baseActivity, - // Include uninstalled apps. Despite its name, adding this flag is a workaround - // to #getActivityInfo throwing a NameNotFoundException for installed packages - // when HSUM is enabled. See b/354884302. - PackageManager.MATCH_UNINSTALLED_PACKAGES); + final PackageManager pm = mUserContext.getPackageManager(); + final ActivityInfo activityInfo = pm.getActivityInfo(baseActivity, 0 /* flags */); final IconProvider provider = new IconProvider(mContext); final Drawable appIconDrawable = provider.getIcon(activityInfo); final BaseIconFactory headerIconFactory = createIconFactory(mContext, @@ -1264,6 +1262,7 @@ public class DesktopModeWindowDecoration extends WindowDecoration<WindowDecorLin DesktopModeWindowDecoration create( Context context, + @NonNull Context userContext, DisplayController displayController, SplitScreenController splitScreenController, ShellTaskOrganizer taskOrganizer, @@ -1277,6 +1276,7 @@ public class DesktopModeWindowDecoration extends WindowDecoration<WindowDecorLin AppToWebGenericLinksParser genericLinksParser) { return new DesktopModeWindowDecoration( context, + userContext, displayController, splitScreenController, taskOrganizer, diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/windowdecor/WindowDecoration.java b/libs/WindowManager/Shell/src/com/android/wm/shell/windowdecor/WindowDecoration.java index 3b8657d4adf5..68285602a26e 100644 --- a/libs/WindowManager/Shell/src/com/android/wm/shell/windowdecor/WindowDecoration.java +++ b/libs/WindowManager/Shell/src/com/android/wm/shell/windowdecor/WindowDecoration.java @@ -106,6 +106,7 @@ public abstract class WindowDecoration<T extends View & TaskFocusStateConsumer> * System-wide context. Only used to create context with overridden configurations. */ final Context mContext; + final @NonNull Context mUserContext; final @NonNull DisplayController mDisplayController; final ShellTaskOrganizer mTaskOrganizer; final Supplier<SurfaceControl.Builder> mSurfaceControlBuilderSupplier; @@ -147,11 +148,12 @@ public abstract class WindowDecoration<T extends View & TaskFocusStateConsumer> WindowDecoration( Context context, + @NonNull Context userContext, DisplayController displayController, ShellTaskOrganizer taskOrganizer, RunningTaskInfo taskInfo, SurfaceControl taskSurface) { - this(context, displayController, taskOrganizer, taskInfo, taskSurface, + this(context, userContext, displayController, taskOrganizer, taskInfo, taskSurface, SurfaceControl.Builder::new, SurfaceControl.Transaction::new, WindowContainerTransaction::new, SurfaceControl::new, new SurfaceControlViewHostFactory() {}); @@ -159,6 +161,7 @@ public abstract class WindowDecoration<T extends View & TaskFocusStateConsumer> WindowDecoration( Context context, + @NonNull Context userContext, @NonNull DisplayController displayController, ShellTaskOrganizer taskOrganizer, RunningTaskInfo taskInfo, @@ -169,6 +172,7 @@ public abstract class WindowDecoration<T extends View & TaskFocusStateConsumer> Supplier<SurfaceControl> surfaceControlSupplier, SurfaceControlViewHostFactory surfaceControlViewHostFactory) { mContext = context; + mUserContext = userContext; mDisplayController = displayController; mTaskOrganizer = taskOrganizer; mTaskInfo = taskInfo; @@ -177,7 +181,6 @@ public abstract class WindowDecoration<T extends View & TaskFocusStateConsumer> mSurfaceControlTransactionSupplier = surfaceControlTransactionSupplier; mWindowContainerTransactionSupplier = windowContainerTransactionSupplier; mSurfaceControlViewHostFactory = surfaceControlViewHostFactory; - mDisplay = mDisplayController.getDisplay(mTaskInfo.displayId); } diff --git a/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/ShellTaskOrganizerTests.java b/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/ShellTaskOrganizerTests.java index e91828be4ebe..716a148175df 100644 --- a/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/ShellTaskOrganizerTests.java +++ b/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/ShellTaskOrganizerTests.java @@ -16,10 +16,6 @@ package com.android.wm.shell; -import static android.app.CameraCompatTaskInfo.CAMERA_COMPAT_CONTROL_DISMISSED; -import static android.app.CameraCompatTaskInfo.CAMERA_COMPAT_CONTROL_HIDDEN; -import static android.app.CameraCompatTaskInfo.CAMERA_COMPAT_CONTROL_TREATMENT_APPLIED; -import static android.app.CameraCompatTaskInfo.CAMERA_COMPAT_CONTROL_TREATMENT_SUGGESTED; import static android.app.WindowConfiguration.WINDOWING_MODE_FREEFORM; import static android.app.WindowConfiguration.WINDOWING_MODE_FULLSCREEN; import static android.app.WindowConfiguration.WINDOWING_MODE_MULTI_WINDOW; @@ -443,84 +439,6 @@ public class ShellTaskOrganizerTests extends ShellTestCase { } @Test - public void testOnCameraCompatActivityChanged() { - final RunningTaskInfo taskInfo1 = createTaskInfo(/* taskId= */ 1, - WINDOWING_MODE_FULLSCREEN); - taskInfo1.displayId = DEFAULT_DISPLAY; - taskInfo1.appCompatTaskInfo.cameraCompatTaskInfo.cameraCompatControlState = - CAMERA_COMPAT_CONTROL_HIDDEN; - final TrackingTaskListener taskListener = new TrackingTaskListener(); - mOrganizer.addListenerForType(taskListener, TASK_LISTENER_TYPE_FULLSCREEN); - mOrganizer.onTaskAppeared(taskInfo1, /* leash= */ null); - - // Task listener sent to compat UI is null if top activity doesn't request a camera - // compat control. - verifyOnCompatInfoChangedInvokedWith(taskInfo1, null /* taskListener */); - - // Task listener is non-null when request a camera compat control for a visible task. - clearInvocations(mCompatUI); - final RunningTaskInfo taskInfo2 = - createTaskInfo(taskInfo1.taskId, taskInfo1.getWindowingMode()); - taskInfo2.displayId = taskInfo1.displayId; - taskInfo2.appCompatTaskInfo.cameraCompatTaskInfo.cameraCompatControlState = - CAMERA_COMPAT_CONTROL_TREATMENT_SUGGESTED; - taskInfo2.isVisible = true; - mOrganizer.onTaskInfoChanged(taskInfo2); - verifyOnCompatInfoChangedInvokedWith(taskInfo2, taskListener); - - // CompatUIController#onCompatInfoChanged is called when requested state for a camera - // compat control changes for a visible task. - clearInvocations(mCompatUI); - final RunningTaskInfo taskInfo3 = - createTaskInfo(taskInfo1.taskId, taskInfo1.getWindowingMode()); - taskInfo3.displayId = taskInfo1.displayId; - taskInfo3.appCompatTaskInfo.cameraCompatTaskInfo.cameraCompatControlState = - CAMERA_COMPAT_CONTROL_TREATMENT_APPLIED; - taskInfo3.isVisible = true; - mOrganizer.onTaskInfoChanged(taskInfo3); - verifyOnCompatInfoChangedInvokedWith(taskInfo3, taskListener); - - // CompatUIController#onCompatInfoChanged is called when a top activity goes in size compat - // mode for a visible task that has a compat control. - clearInvocations(mCompatUI); - final RunningTaskInfo taskInfo4 = - createTaskInfo(taskInfo1.taskId, taskInfo1.getWindowingMode()); - taskInfo4.displayId = taskInfo1.displayId; - taskInfo4.appCompatTaskInfo.topActivityInSizeCompat = true; - taskInfo4.appCompatTaskInfo.cameraCompatTaskInfo.cameraCompatControlState = - CAMERA_COMPAT_CONTROL_TREATMENT_APPLIED; - taskInfo4.isVisible = true; - mOrganizer.onTaskInfoChanged(taskInfo4); - verifyOnCompatInfoChangedInvokedWith(taskInfo4, taskListener); - - // Task linster is null when a camera compat control is dimissed for a visible task. - clearInvocations(mCompatUI); - final RunningTaskInfo taskInfo5 = - createTaskInfo(taskInfo1.taskId, taskInfo1.getWindowingMode()); - taskInfo5.displayId = taskInfo1.displayId; - taskInfo5.appCompatTaskInfo.cameraCompatTaskInfo.cameraCompatControlState = - CAMERA_COMPAT_CONTROL_DISMISSED; - taskInfo5.isVisible = true; - mOrganizer.onTaskInfoChanged(taskInfo5); - verifyOnCompatInfoChangedInvokedWith(taskInfo5, null /* taskListener */); - - // Task linster is null when request a camera compat control for a invisible task. - clearInvocations(mCompatUI); - final RunningTaskInfo taskInfo6 = - createTaskInfo(taskInfo1.taskId, taskInfo1.getWindowingMode()); - taskInfo6.displayId = taskInfo1.displayId; - taskInfo6.appCompatTaskInfo.cameraCompatTaskInfo.cameraCompatControlState = - CAMERA_COMPAT_CONTROL_TREATMENT_SUGGESTED; - taskInfo6.isVisible = false; - mOrganizer.onTaskInfoChanged(taskInfo6); - verifyOnCompatInfoChangedInvokedWith(taskInfo6, null /* taskListener */); - - clearInvocations(mCompatUI); - mOrganizer.onTaskVanished(taskInfo1); - verifyOnCompatInfoChangedInvokedWith(taskInfo1, null /* taskListener */); - } - - @Test public void testAddLocusListener() { RunningTaskInfo task1 = createTaskInfo(/* taskId= */ 1, WINDOWING_MODE_MULTI_WINDOW); task1.isVisible = true; diff --git a/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/common/DisplayImeControllerTest.java b/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/common/DisplayImeControllerTest.java index 2c0aa12f22d2..764d5a97e3e1 100644 --- a/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/common/DisplayImeControllerTest.java +++ b/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/common/DisplayImeControllerTest.java @@ -83,7 +83,7 @@ public class DisplayImeControllerTest extends ShellTestCase { } }, mExecutor) { @Override - void removeImeSurface() { } + void removeImeSurface(int displayId) { } }.new PerDisplay(DEFAULT_DISPLAY, ROTATION_0); } diff --git a/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/compatui/CompatUIControllerTest.java b/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/compatui/CompatUIControllerTest.java index fc7a7770b8ca..77e22cd17f6f 100644 --- a/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/compatui/CompatUIControllerTest.java +++ b/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/compatui/CompatUIControllerTest.java @@ -16,8 +16,6 @@ package com.android.wm.shell.compatui; -import static android.app.CameraCompatTaskInfo.CAMERA_COMPAT_CONTROL_HIDDEN; -import static android.app.CameraCompatTaskInfo.CAMERA_COMPAT_CONTROL_TREATMENT_APPLIED; import static android.view.WindowInsets.Type.navigationBars; import static com.android.dx.mockito.inline.extended.ExtendedMockito.spyOn; @@ -34,7 +32,6 @@ import static org.mockito.Mockito.times; import static org.mockito.Mockito.verify; import android.app.ActivityManager.RunningTaskInfo; -import android.app.CameraCompatTaskInfo.CameraCompatControlState; import android.app.TaskInfo; import android.content.Context; import android.content.res.Configuration; @@ -199,8 +196,7 @@ public class CompatUIControllerTest extends ShellTestCase { @Test @RequiresFlagsDisabled(Flags.FLAG_APP_COMPAT_UI_FRAMEWORK) public void testOnCompatInfoChanged() { - TaskInfo taskInfo = createTaskInfo(DISPLAY_ID, TASK_ID, /* hasSizeCompat= */ true, - CAMERA_COMPAT_CONTROL_HIDDEN); + TaskInfo taskInfo = createTaskInfo(DISPLAY_ID, TASK_ID, /* hasSizeCompat= */ true); // Verify that the compat controls are added with non-null task listener. mController.onCompatInfoChanged(new CompatUIInfo(taskInfo, mMockTaskListener)); @@ -214,8 +210,7 @@ public class CompatUIControllerTest extends ShellTestCase { // Verify that the compat controls and letterbox education are updated with new size compat // info. clearInvocations(mMockCompatLayout, mMockLetterboxEduLayout, mController); - taskInfo = createTaskInfo(DISPLAY_ID, TASK_ID, /* hasSizeCompat= */ true, - CAMERA_COMPAT_CONTROL_TREATMENT_APPLIED); + taskInfo = createTaskInfo(DISPLAY_ID, TASK_ID, /* hasSizeCompat= */ true); mController.onCompatInfoChanged(new CompatUIInfo(taskInfo, mMockTaskListener)); verify(mMockCompatLayout).updateCompatInfo(taskInfo, mMockTaskListener, @@ -228,7 +223,7 @@ public class CompatUIControllerTest extends ShellTestCase { // Verify that compat controls and letterbox education are removed with null task listener. clearInvocations(mMockCompatLayout, mMockLetterboxEduLayout, mController); mController.onCompatInfoChanged(new CompatUIInfo(createTaskInfo(DISPLAY_ID, TASK_ID, - /* hasSizeCompat= */ true, CAMERA_COMPAT_CONTROL_HIDDEN), + /* hasSizeCompat= */ true), /* taskListener= */ null)); verify(mMockCompatLayout).release(); @@ -243,8 +238,7 @@ public class CompatUIControllerTest extends ShellTestCase { doReturn(false).when(mMockLetterboxEduLayout).createLayout(anyBoolean()); doReturn(false).when(mMockRestartDialogLayout).createLayout(anyBoolean()); - TaskInfo taskInfo = createTaskInfo(DISPLAY_ID, TASK_ID, /* hasSizeCompat= */ true, - CAMERA_COMPAT_CONTROL_HIDDEN); + TaskInfo taskInfo = createTaskInfo(DISPLAY_ID, TASK_ID, /* hasSizeCompat= */ true); mController.onCompatInfoChanged(new CompatUIInfo(taskInfo, mMockTaskListener)); verify(mController).createCompatUiWindowManager(any(), eq(taskInfo), eq(mMockTaskListener)); @@ -274,8 +268,7 @@ public class CompatUIControllerTest extends ShellTestCase { doReturn(false).when(mMockLetterboxEduLayout).updateCompatInfo(any(), any(), anyBoolean()); doReturn(false).when(mMockRestartDialogLayout).updateCompatInfo(any(), any(), anyBoolean()); - TaskInfo taskInfo = createTaskInfo(DISPLAY_ID, TASK_ID, /* hasSizeCompat= */ true, - CAMERA_COMPAT_CONTROL_HIDDEN); + TaskInfo taskInfo = createTaskInfo(DISPLAY_ID, TASK_ID, /* hasSizeCompat= */ true); mController.onCompatInfoChanged(new CompatUIInfo(taskInfo, mMockTaskListener)); verify(mController).createCompatUiWindowManager(any(), eq(taskInfo), eq(mMockTaskListener)); @@ -326,7 +319,7 @@ public class CompatUIControllerTest extends ShellTestCase { public void testOnDisplayRemoved() { mController.onDisplayAdded(DISPLAY_ID); mController.onCompatInfoChanged(new CompatUIInfo(createTaskInfo(DISPLAY_ID, TASK_ID, - /* hasSizeCompat= */ true, CAMERA_COMPAT_CONTROL_HIDDEN), mMockTaskListener)); + /* hasSizeCompat= */ true), mMockTaskListener)); mController.onDisplayRemoved(DISPLAY_ID + 1); @@ -348,7 +341,7 @@ public class CompatUIControllerTest extends ShellTestCase { @RequiresFlagsDisabled(Flags.FLAG_APP_COMPAT_UI_FRAMEWORK) public void testOnDisplayConfigurationChanged() { mController.onCompatInfoChanged(new CompatUIInfo(createTaskInfo(DISPLAY_ID, TASK_ID, - /* hasSizeCompat= */ true, CAMERA_COMPAT_CONTROL_HIDDEN), mMockTaskListener)); + /* hasSizeCompat= */ true), mMockTaskListener)); mController.onDisplayConfigurationChanged(DISPLAY_ID + 1, new Configuration()); @@ -368,7 +361,7 @@ public class CompatUIControllerTest extends ShellTestCase { public void testInsetsChanged() { mController.onDisplayAdded(DISPLAY_ID); mController.onCompatInfoChanged(new CompatUIInfo(createTaskInfo(DISPLAY_ID, TASK_ID, - /* hasSizeCompat= */ true, CAMERA_COMPAT_CONTROL_HIDDEN), mMockTaskListener)); + /* hasSizeCompat= */ true), mMockTaskListener)); InsetsState insetsState = new InsetsState(); InsetsSource insetsSource = new InsetsSource( InsetsSource.createId(null, 0, navigationBars()), navigationBars()); @@ -395,7 +388,7 @@ public class CompatUIControllerTest extends ShellTestCase { @RequiresFlagsDisabled(Flags.FLAG_APP_COMPAT_UI_FRAMEWORK) public void testChangeLayoutsVisibilityOnImeShowHide() { mController.onCompatInfoChanged(new CompatUIInfo(createTaskInfo(DISPLAY_ID, TASK_ID, - /* hasSizeCompat= */ true, CAMERA_COMPAT_CONTROL_HIDDEN), mMockTaskListener)); + /* hasSizeCompat= */ true), mMockTaskListener)); // Verify that the restart button is hidden after IME is showing. mController.onImeVisibilityChanged(DISPLAY_ID, /* isShowing= */ true); @@ -405,8 +398,7 @@ public class CompatUIControllerTest extends ShellTestCase { verify(mMockRestartDialogLayout).updateVisibility(false); // Verify button remains hidden while IME is showing. - TaskInfo taskInfo = createTaskInfo(DISPLAY_ID, TASK_ID, /* hasSizeCompat= */ true, - CAMERA_COMPAT_CONTROL_HIDDEN); + TaskInfo taskInfo = createTaskInfo(DISPLAY_ID, TASK_ID, /* hasSizeCompat= */ true); mController.onCompatInfoChanged(new CompatUIInfo(taskInfo, mMockTaskListener)); verify(mMockCompatLayout).updateCompatInfo(taskInfo, mMockTaskListener, @@ -428,7 +420,7 @@ public class CompatUIControllerTest extends ShellTestCase { @RequiresFlagsDisabled(Flags.FLAG_APP_COMPAT_UI_FRAMEWORK) public void testChangeLayoutsVisibilityOnKeyguardShowingChanged() { mController.onCompatInfoChanged(new CompatUIInfo(createTaskInfo(DISPLAY_ID, TASK_ID, - /* hasSizeCompat= */ true, CAMERA_COMPAT_CONTROL_HIDDEN), mMockTaskListener)); + /* hasSizeCompat= */ true), mMockTaskListener)); // Verify that the restart button is hidden after keyguard becomes showing. mController.onKeyguardVisibilityChanged(true, false, false); @@ -438,8 +430,7 @@ public class CompatUIControllerTest extends ShellTestCase { verify(mMockRestartDialogLayout).updateVisibility(false); // Verify button remains hidden while keyguard is showing. - TaskInfo taskInfo = createTaskInfo(DISPLAY_ID, TASK_ID, /* hasSizeCompat= */ true, - CAMERA_COMPAT_CONTROL_HIDDEN); + TaskInfo taskInfo = createTaskInfo(DISPLAY_ID, TASK_ID, /* hasSizeCompat= */ true); mController.onCompatInfoChanged(new CompatUIInfo(taskInfo, mMockTaskListener)); verify(mMockCompatLayout).updateCompatInfo(taskInfo, mMockTaskListener, @@ -461,7 +452,7 @@ public class CompatUIControllerTest extends ShellTestCase { @RequiresFlagsDisabled(Flags.FLAG_APP_COMPAT_UI_FRAMEWORK) public void testLayoutsRemainHiddenOnKeyguardShowingFalseWhenImeIsShowing() { mController.onCompatInfoChanged(new CompatUIInfo(createTaskInfo(DISPLAY_ID, TASK_ID, - /* hasSizeCompat= */ true, CAMERA_COMPAT_CONTROL_HIDDEN), mMockTaskListener)); + /* hasSizeCompat= */ true), mMockTaskListener)); mController.onImeVisibilityChanged(DISPLAY_ID, /* isShowing= */ true); mController.onKeyguardVisibilityChanged(true, false, false); @@ -491,7 +482,7 @@ public class CompatUIControllerTest extends ShellTestCase { @RequiresFlagsDisabled(Flags.FLAG_APP_COMPAT_UI_FRAMEWORK) public void testLayoutsRemainHiddenOnImeHideWhenKeyguardIsShowing() { mController.onCompatInfoChanged(new CompatUIInfo(createTaskInfo(DISPLAY_ID, TASK_ID, - /* hasSizeCompat= */ true, CAMERA_COMPAT_CONTROL_HIDDEN), mMockTaskListener)); + /* hasSizeCompat= */ true), mMockTaskListener)); mController.onImeVisibilityChanged(DISPLAY_ID, /* isShowing= */ true); mController.onKeyguardVisibilityChanged(true, false, false); @@ -520,8 +511,7 @@ public class CompatUIControllerTest extends ShellTestCase { @Test @RequiresFlagsDisabled(Flags.FLAG_APP_COMPAT_UI_FRAMEWORK) public void testRestartLayoutRecreatedIfNeeded() { - final TaskInfo taskInfo = createTaskInfo(DISPLAY_ID, TASK_ID, - /* hasSizeCompat= */ true, CAMERA_COMPAT_CONTROL_HIDDEN); + final TaskInfo taskInfo = createTaskInfo(DISPLAY_ID, TASK_ID, /* hasSizeCompat= */ true); doReturn(true).when(mMockRestartDialogLayout) .needsToBeRecreated(any(TaskInfo.class), any(ShellTaskOrganizer.TaskListener.class)); @@ -536,8 +526,7 @@ public class CompatUIControllerTest extends ShellTestCase { @Test @RequiresFlagsDisabled(Flags.FLAG_APP_COMPAT_UI_FRAMEWORK) public void testRestartLayoutNotRecreatedIfNotNeeded() { - final TaskInfo taskInfo = createTaskInfo(DISPLAY_ID, TASK_ID, - /* hasSizeCompat= */ true, CAMERA_COMPAT_CONTROL_HIDDEN); + final TaskInfo taskInfo = createTaskInfo(DISPLAY_ID, TASK_ID, /* hasSizeCompat= */ true); doReturn(false).when(mMockRestartDialogLayout) .needsToBeRecreated(any(TaskInfo.class), any(ShellTaskOrganizer.TaskListener.class)); @@ -557,9 +546,8 @@ public class CompatUIControllerTest extends ShellTestCase { Assert.assertTrue(mController.hasShownUserAspectRatioSettingsButton()); // Create new task - final TaskInfo taskInfo = createTaskInfo(DISPLAY_ID, TASK_ID, - /* hasSizeCompat= */ true, CAMERA_COMPAT_CONTROL_HIDDEN, /* isVisible */ true, - /* isFocused */ true); + final TaskInfo taskInfo = createTaskInfo(DISPLAY_ID, TASK_ID, /* hasSizeCompat= */ true, + /* isVisible */ true, /* isFocused */ true); // Simulate new task being shown mController.updateActiveTaskInfo(taskInfo); @@ -574,9 +562,8 @@ public class CompatUIControllerTest extends ShellTestCase { @RequiresFlagsDisabled(Flags.FLAG_APP_COMPAT_UI_FRAMEWORK) public void testUpdateActiveTaskInfo_newTask_notVisibleOrFocused_notUpdated() { // Create new task - final TaskInfo taskInfo = createTaskInfo(DISPLAY_ID, TASK_ID, - /* hasSizeCompat= */ true, CAMERA_COMPAT_CONTROL_HIDDEN, /* isVisible */ true, - /* isFocused */ true); + final TaskInfo taskInfo = createTaskInfo(DISPLAY_ID, TASK_ID, /* hasSizeCompat= */ true, + /* isVisible */ true, /* isFocused */ true); // Simulate task being shown mController.updateActiveTaskInfo(taskInfo); @@ -593,9 +580,8 @@ public class CompatUIControllerTest extends ShellTestCase { final int newTaskId = TASK_ID + 1; // Create visible but NOT focused task - final TaskInfo taskInfo1 = createTaskInfo(DISPLAY_ID, newTaskId, - /* hasSizeCompat= */ true, CAMERA_COMPAT_CONTROL_HIDDEN, /* isVisible */ true, - /* isFocused */ false); + final TaskInfo taskInfo1 = createTaskInfo(DISPLAY_ID, newTaskId, /* hasSizeCompat= */ true, + /* isVisible */ true, /* isFocused */ false); // Simulate new task being shown mController.updateActiveTaskInfo(taskInfo1); @@ -606,9 +592,8 @@ public class CompatUIControllerTest extends ShellTestCase { Assert.assertTrue(mController.hasShownUserAspectRatioSettingsButton()); // Create focused but NOT visible task - final TaskInfo taskInfo2 = createTaskInfo(DISPLAY_ID, newTaskId, - /* hasSizeCompat= */ true, CAMERA_COMPAT_CONTROL_HIDDEN, /* isVisible */ false, - /* isFocused */ true); + final TaskInfo taskInfo2 = createTaskInfo(DISPLAY_ID, newTaskId, /* hasSizeCompat= */ true, + /* isVisible */ false, /* isFocused */ true); // Simulate new task being shown mController.updateActiveTaskInfo(taskInfo2); @@ -619,9 +604,8 @@ public class CompatUIControllerTest extends ShellTestCase { Assert.assertTrue(mController.hasShownUserAspectRatioSettingsButton()); // Create NOT focused but NOT visible task - final TaskInfo taskInfo3 = createTaskInfo(DISPLAY_ID, newTaskId, - /* hasSizeCompat= */ true, CAMERA_COMPAT_CONTROL_HIDDEN, /* isVisible */ false, - /* isFocused */ false); + final TaskInfo taskInfo3 = createTaskInfo(DISPLAY_ID, newTaskId, /* hasSizeCompat= */ true, + /* isVisible */ false, /* isFocused */ false); // Simulate new task being shown mController.updateActiveTaskInfo(taskInfo3); @@ -636,9 +620,8 @@ public class CompatUIControllerTest extends ShellTestCase { @RequiresFlagsDisabled(Flags.FLAG_APP_COMPAT_UI_FRAMEWORK) public void testUpdateActiveTaskInfo_sameTask_notUpdated() { // Create new task - final TaskInfo taskInfo = createTaskInfo(DISPLAY_ID, TASK_ID, - /* hasSizeCompat= */ true, CAMERA_COMPAT_CONTROL_HIDDEN, /* isVisible */ true, - /* isFocused */ true); + final TaskInfo taskInfo = createTaskInfo(DISPLAY_ID, TASK_ID, /* hasSizeCompat= */ true, + /* isVisible */ true, /* isFocused */ true); // Simulate new task being shown mController.updateActiveTaskInfo(taskInfo); @@ -665,9 +648,8 @@ public class CompatUIControllerTest extends ShellTestCase { @RequiresFlagsDisabled(Flags.FLAG_APP_COMPAT_UI_FRAMEWORK) public void testUpdateActiveTaskInfo_transparentTask_notUpdated() { // Create new task - final TaskInfo taskInfo = createTaskInfo(DISPLAY_ID, TASK_ID, - /* hasSizeCompat= */ true, CAMERA_COMPAT_CONTROL_HIDDEN, /* isVisible */ true, - /* isFocused */ true); + final TaskInfo taskInfo = createTaskInfo(DISPLAY_ID, TASK_ID, /* hasSizeCompat= */ true, + /* isVisible */ true, /* isFocused */ true); // Simulate new task being shown mController.updateActiveTaskInfo(taskInfo); @@ -684,9 +666,8 @@ public class CompatUIControllerTest extends ShellTestCase { final int newTaskId = TASK_ID + 1; // Create transparent task - final TaskInfo taskInfo1 = createTaskInfo(DISPLAY_ID, newTaskId, - /* hasSizeCompat= */ true, CAMERA_COMPAT_CONTROL_HIDDEN, /* isVisible */ true, - /* isFocused */ true, /* isTopActivityTransparent */ true); + final TaskInfo taskInfo1 = createTaskInfo(DISPLAY_ID, newTaskId, /* hasSizeCompat= */ true, + /* isVisible */ true, /* isFocused */ true, /* isTopActivityTransparent */ true); // Simulate new task being shown mController.updateActiveTaskInfo(taskInfo1); @@ -699,8 +680,7 @@ public class CompatUIControllerTest extends ShellTestCase { @Test public void testLetterboxEduLayout_notCreatedWhenLetterboxEducationIsDisabled() { - TaskInfo taskInfo = createTaskInfo(DISPLAY_ID, TASK_ID, /* hasSizeCompat= */ true, - CAMERA_COMPAT_CONTROL_HIDDEN); + TaskInfo taskInfo = createTaskInfo(DISPLAY_ID, TASK_ID, /* hasSizeCompat= */ true); taskInfo.appCompatTaskInfo.isLetterboxEducationEnabled = false; mController.onCompatInfoChanged(new CompatUIInfo(taskInfo, mMockTaskListener)); @@ -709,29 +689,23 @@ public class CompatUIControllerTest extends ShellTestCase { eq(mMockTaskListener)); } - private static TaskInfo createTaskInfo(int displayId, int taskId, boolean hasSizeCompat, - @CameraCompatControlState int cameraCompatControlState) { - return createTaskInfo(displayId, taskId, hasSizeCompat, cameraCompatControlState, - /* isVisible */ false, /* isFocused */ false, - /* isTopActivityTransparent */ false); + private static TaskInfo createTaskInfo(int displayId, int taskId, boolean hasSizeCompat) { + return createTaskInfo(displayId, taskId, hasSizeCompat, /* isVisible */ false, + /* isFocused */ false, /* isTopActivityTransparent */ false); } private static TaskInfo createTaskInfo(int displayId, int taskId, boolean hasSizeCompat, - @CameraCompatControlState int cameraCompatControlState, boolean isVisible, - boolean isFocused) { - return createTaskInfo(displayId, taskId, hasSizeCompat, cameraCompatControlState, + boolean isVisible, boolean isFocused) { + return createTaskInfo(displayId, taskId, hasSizeCompat, isVisible, isFocused, /* isTopActivityTransparent */ false); } private static TaskInfo createTaskInfo(int displayId, int taskId, boolean hasSizeCompat, - @CameraCompatControlState int cameraCompatControlState, boolean isVisible, - boolean isFocused, boolean isTopActivityTransparent) { + boolean isVisible, boolean isFocused, boolean isTopActivityTransparent) { RunningTaskInfo taskInfo = new RunningTaskInfo(); taskInfo.taskId = taskId; taskInfo.displayId = displayId; taskInfo.appCompatTaskInfo.topActivityInSizeCompat = hasSizeCompat; - taskInfo.appCompatTaskInfo.cameraCompatTaskInfo.cameraCompatControlState = - cameraCompatControlState; taskInfo.isVisible = isVisible; taskInfo.isFocused = isFocused; taskInfo.isTopActivityTransparent = isTopActivityTransparent; diff --git a/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/compatui/CompatUILayoutTest.java b/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/compatui/CompatUILayoutTest.java index 33d69f5c34c8..3b93861d6cd2 100644 --- a/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/compatui/CompatUILayoutTest.java +++ b/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/compatui/CompatUILayoutTest.java @@ -16,20 +16,13 @@ package com.android.wm.shell.compatui; -import static android.app.CameraCompatTaskInfo.CAMERA_COMPAT_CONTROL_DISMISSED; -import static android.app.CameraCompatTaskInfo.CAMERA_COMPAT_CONTROL_HIDDEN; -import static android.app.CameraCompatTaskInfo.CAMERA_COMPAT_CONTROL_TREATMENT_APPLIED; -import static android.app.CameraCompatTaskInfo.CAMERA_COMPAT_CONTROL_TREATMENT_SUGGESTED; - import static com.android.dx.mockito.inline.extended.ExtendedMockito.spyOn; -import static org.mockito.Mockito.clearInvocations; import static org.mockito.Mockito.doNothing; import static org.mockito.Mockito.doReturn; import static org.mockito.Mockito.verify; import android.app.ActivityManager; -import android.app.CameraCompatTaskInfo.CameraCompatControlState; import android.app.TaskInfo; import android.graphics.Rect; import android.platform.test.annotations.RequiresFlagsDisabled; @@ -52,7 +45,6 @@ import com.android.wm.shell.common.DisplayLayout; import com.android.wm.shell.common.SyncTransactionQueue; import com.android.wm.shell.compatui.CompatUIController.CompatUIHintsState; import com.android.wm.shell.compatui.api.CompatUIEvent; -import com.android.wm.shell.compatui.impl.CompatUIEvents; import junit.framework.Assert; @@ -97,7 +89,7 @@ public class CompatUILayoutTest extends ShellTestCase { public void setUp() { MockitoAnnotations.initMocks(this); doReturn(100).when(mCompatUIConfiguration).getHideSizeCompatRestartButtonTolerance(); - mTaskInfo = createTaskInfo(/* hasSizeCompat= */ false, CAMERA_COMPAT_CONTROL_HIDDEN); + mTaskInfo = createTaskInfo(/* hasSizeCompat= */ false); mWindowManager = new CompatUIWindowManager(mContext, mTaskInfo, mSyncTransactionQueue, mCallback, mTaskListener, new DisplayLayout(), new CompatUIHintsState(), mCompatUIConfiguration, mOnRestartButtonClicked); @@ -151,113 +143,13 @@ public class CompatUILayoutTest extends ShellTestCase { verify(mLayout).setSizeCompatHintVisibility(/* show= */ false); } - @Test - @RequiresFlagsDisabled(Flags.FLAG_APP_COMPAT_UI_FRAMEWORK) - public void testUpdateCameraTreatmentButton_treatmentAppliedByDefault() { - mWindowManager.mCameraCompatControlState = CAMERA_COMPAT_CONTROL_TREATMENT_APPLIED; - mWindowManager.createLayout(/* canShow= */ true); - final ImageButton button = - mLayout.findViewById(R.id.camera_compat_treatment_button); - button.performClick(); - - verify(mWindowManager).onCameraTreatmentButtonClicked(); - verifyOnCameraControlStateUpdatedInvokedWith(TASK_ID, - CAMERA_COMPAT_CONTROL_TREATMENT_SUGGESTED); - - button.performClick(); - - verifyOnCameraControlStateUpdatedInvokedWith(TASK_ID, - CAMERA_COMPAT_CONTROL_TREATMENT_APPLIED); - } - - @Test - @RequiresFlagsDisabled(Flags.FLAG_APP_COMPAT_UI_FRAMEWORK) - public void testUpdateCameraTreatmentButton_treatmentSuggestedByDefault() { - mWindowManager.mCameraCompatControlState = CAMERA_COMPAT_CONTROL_TREATMENT_SUGGESTED; - mWindowManager.createLayout(/* canShow= */ true); - final ImageButton button = - mLayout.findViewById(R.id.camera_compat_treatment_button); - button.performClick(); - - verify(mWindowManager).onCameraTreatmentButtonClicked(); - verifyOnCameraControlStateUpdatedInvokedWith(TASK_ID, - CAMERA_COMPAT_CONTROL_TREATMENT_APPLIED); - - button.performClick(); - - verifyOnCameraControlStateUpdatedInvokedWith(TASK_ID, - CAMERA_COMPAT_CONTROL_TREATMENT_SUGGESTED); - } - - @Test - @RequiresFlagsDisabled(Flags.FLAG_APP_COMPAT_UI_FRAMEWORK) - public void testOnCameraDismissButtonClicked() { - mWindowManager.mCameraCompatControlState = CAMERA_COMPAT_CONTROL_TREATMENT_SUGGESTED; - mWindowManager.createLayout(/* canShow= */ true); - final ImageButton button = - mLayout.findViewById(R.id.camera_compat_dismiss_button); - button.performClick(); - - verify(mWindowManager).onCameraDismissButtonClicked(); - verifyOnCameraControlStateUpdatedInvokedWith(TASK_ID, CAMERA_COMPAT_CONTROL_DISMISSED); - verify(mLayout).setCameraControlVisibility(/* show */ false); - } - - @Test - @RequiresFlagsDisabled(Flags.FLAG_APP_COMPAT_UI_FRAMEWORK) - public void testOnLongClickForCameraTreatmentButton() { - doNothing().when(mWindowManager).onCameraButtonLongClicked(); - - final ImageButton button = - mLayout.findViewById(R.id.camera_compat_treatment_button); - button.performLongClick(); - - verify(mWindowManager).onCameraButtonLongClicked(); - } - - @Test - @RequiresFlagsDisabled(Flags.FLAG_APP_COMPAT_UI_FRAMEWORK) - public void testOnLongClickForCameraDismissButton() { - doNothing().when(mWindowManager).onCameraButtonLongClicked(); - - final ImageButton button = mLayout.findViewById(R.id.camera_compat_dismiss_button); - button.performLongClick(); - - verify(mWindowManager).onCameraButtonLongClicked(); - } - - @Test - @RequiresFlagsDisabled(Flags.FLAG_APP_COMPAT_UI_FRAMEWORK) - public void testOnClickForCameraCompatHint() { - mWindowManager.mCameraCompatControlState = CAMERA_COMPAT_CONTROL_TREATMENT_SUGGESTED; - mWindowManager.createLayout(/* canShow= */ true); - final LinearLayout hint = mLayout.findViewById(R.id.camera_compat_hint); - hint.performClick(); - - verify(mLayout).setCameraCompatHintVisibility(/* show= */ false); - } - - private static TaskInfo createTaskInfo(boolean hasSizeCompat, - @CameraCompatControlState int cameraCompatControlState) { + private static TaskInfo createTaskInfo(boolean hasSizeCompat) { ActivityManager.RunningTaskInfo taskInfo = new ActivityManager.RunningTaskInfo(); taskInfo.taskId = TASK_ID; taskInfo.appCompatTaskInfo.topActivityInSizeCompat = hasSizeCompat; - taskInfo.appCompatTaskInfo.cameraCompatTaskInfo.cameraCompatControlState = - cameraCompatControlState; taskInfo.appCompatTaskInfo.topActivityLetterboxHeight = 1000; taskInfo.appCompatTaskInfo.topActivityLetterboxWidth = 1000; taskInfo.configuration.windowConfiguration.setBounds(new Rect(0, 0, 2000, 2000)); return taskInfo; } - - private void verifyOnCameraControlStateUpdatedInvokedWith(int taskId, int state) { - final ArgumentCaptor<CompatUIEvent> captureValue = ArgumentCaptor.forClass( - CompatUIEvent.class); - verify(mCallback).accept(captureValue.capture()); - final CompatUIEvents.CameraControlStateUpdated compatUIEvent = - (CompatUIEvents.CameraControlStateUpdated) captureValue.getValue(); - Assert.assertEquals((compatUIEvent).getTaskId(), taskId); - Assert.assertEquals((compatUIEvent).getState(), state); - clearInvocations(mCallback); - } } diff --git a/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/compatui/CompatUIWindowManagerTest.java b/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/compatui/CompatUIWindowManagerTest.java index eb3da8f65b5d..c5033f3ae64b 100644 --- a/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/compatui/CompatUIWindowManagerTest.java +++ b/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/compatui/CompatUIWindowManagerTest.java @@ -16,10 +16,6 @@ package com.android.wm.shell.compatui; -import static android.app.CameraCompatTaskInfo.CAMERA_COMPAT_CONTROL_DISMISSED; -import static android.app.CameraCompatTaskInfo.CAMERA_COMPAT_CONTROL_HIDDEN; -import static android.app.CameraCompatTaskInfo.CAMERA_COMPAT_CONTROL_TREATMENT_APPLIED; -import static android.app.CameraCompatTaskInfo.CAMERA_COMPAT_CONTROL_TREATMENT_SUGGESTED; import static android.platform.test.flag.junit.SetFlagsRule.DefaultInitValueType.DEVICE_DEFAULT; import static android.view.WindowInsets.Type.navigationBars; import static android.view.WindowManager.LARGE_SCREEN_SMALLEST_SCREEN_WIDTH_DP; @@ -36,10 +32,10 @@ import static org.mockito.Mockito.clearInvocations; import static org.mockito.Mockito.doReturn; import static org.mockito.Mockito.mock; import static org.mockito.Mockito.never; +import static org.mockito.Mockito.times; import static org.mockito.Mockito.verify; import android.app.ActivityManager; -import android.app.CameraCompatTaskInfo; import android.app.TaskInfo; import android.content.res.Configuration; import android.graphics.Rect; @@ -65,7 +61,6 @@ import com.android.wm.shell.common.DisplayLayout; import com.android.wm.shell.common.SyncTransactionQueue; import com.android.wm.shell.compatui.CompatUIController.CompatUIHintsState; import com.android.wm.shell.compatui.api.CompatUIEvent; -import com.android.wm.shell.compatui.impl.CompatUIEvents; import junit.framework.Assert; @@ -115,7 +110,7 @@ public class CompatUIWindowManagerTest extends ShellTestCase { public void setUp() { MockitoAnnotations.initMocks(this); doReturn(100).when(mCompatUIConfiguration).getHideSizeCompatRestartButtonTolerance(); - mTaskInfo = createTaskInfo(/* hasSizeCompat= */ false, CAMERA_COMPAT_CONTROL_HIDDEN); + mTaskInfo = createTaskInfo(/* hasSizeCompat= */ false); final DisplayInfo displayInfo = new DisplayInfo(); displayInfo.logicalWidth = TASK_WIDTH; @@ -186,45 +181,6 @@ public class CompatUIWindowManagerTest extends ShellTestCase { @Test @RequiresFlagsDisabled(FLAG_APP_COMPAT_UI_FRAMEWORK) - public void testCreateCameraCompatControl() { - // Doesn't create layout if show is false. - mWindowManager.mCameraCompatControlState = CAMERA_COMPAT_CONTROL_TREATMENT_SUGGESTED; - assertTrue(mWindowManager.createLayout(/* canShow= */ false)); - - verify(mWindowManager, never()).inflateLayout(); - - // Doesn't create hint popup. - mWindowManager.mCompatUIHintsState.mHasShownCameraCompatHint = true; - assertTrue(mWindowManager.createLayout(/* canShow= */ true)); - - verify(mWindowManager).inflateLayout(); - verify(mLayout).setCameraControlVisibility(/* show= */ true); - verify(mLayout, never()).setCameraCompatHintVisibility(/* show= */ true); - - // Creates hint popup. - clearInvocations(mWindowManager); - clearInvocations(mLayout); - mWindowManager.release(); - mWindowManager.mCompatUIHintsState.mHasShownCameraCompatHint = false; - assertTrue(mWindowManager.createLayout(/* canShow= */ true)); - - verify(mWindowManager).inflateLayout(); - assertNotNull(mLayout); - verify(mLayout).setCameraControlVisibility(/* show= */ true); - verify(mLayout).setCameraCompatHintVisibility(/* show= */ true); - assertTrue(mWindowManager.mCompatUIHintsState.mHasShownCameraCompatHint); - - // Returns false and doesn't create layout if Camera Compat state is hidden - clearInvocations(mWindowManager); - mWindowManager.release(); - mWindowManager.mCameraCompatControlState = CAMERA_COMPAT_CONTROL_HIDDEN; - assertFalse(mWindowManager.createLayout(/* canShow= */ true)); - - verify(mWindowManager, never()).inflateLayout(); - } - - @Test - @RequiresFlagsDisabled(FLAG_APP_COMPAT_UI_FRAMEWORK) public void testRelease() { mWindowManager.mHasSizeCompat = true; mWindowManager.createLayout(/* canShow= */ true); @@ -241,10 +197,11 @@ public class CompatUIWindowManagerTest extends ShellTestCase { public void testUpdateCompatInfo() { mWindowManager.mHasSizeCompat = true; mWindowManager.createLayout(/* canShow= */ true); + verify(mLayout).setRestartButtonVisibility(/* show= */ true); // No diff clearInvocations(mWindowManager); - TaskInfo taskInfo = createTaskInfo(/* hasSizeCompat= */ true, CAMERA_COMPAT_CONTROL_HIDDEN); + TaskInfo taskInfo = createTaskInfo(/* hasSizeCompat= */ true); doReturn(true).when(mWindowManager).shouldShowSizeCompatRestartButton(any()); assertTrue(mWindowManager.updateCompatInfo(taskInfo, mTaskListener, /* canShow= */ true)); @@ -261,58 +218,25 @@ public class CompatUIWindowManagerTest extends ShellTestCase { verify(mWindowManager).release(); verify(mWindowManager).createLayout(/* canShow= */ true); - // Change Camera Compat state, show a control. - clearInvocations(mWindowManager); - clearInvocations(mLayout); - taskInfo = createTaskInfo(/* hasSizeCompat= */ true, - CAMERA_COMPAT_CONTROL_TREATMENT_APPLIED); - assertTrue(mWindowManager.updateCompatInfo(taskInfo, newTaskListener, /* canShow= */ true)); - - verify(mLayout).setCameraControlVisibility(/* show= */ true); - verify(mLayout).updateCameraTreatmentButton( - CAMERA_COMPAT_CONTROL_TREATMENT_APPLIED); - - // Change Camera Compat state, update a control. - clearInvocations(mWindowManager); - clearInvocations(mLayout); - taskInfo = createTaskInfo(/* hasSizeCompat= */ true, - CAMERA_COMPAT_CONTROL_TREATMENT_SUGGESTED); - assertTrue(mWindowManager.updateCompatInfo(taskInfo, newTaskListener, /* canShow= */ true)); - - verify(mLayout).setCameraControlVisibility(/* show= */ true); - verify(mLayout).updateCameraTreatmentButton( - CAMERA_COMPAT_CONTROL_TREATMENT_SUGGESTED); - - // Change has Size Compat to false, hides restart button. + // Change has Size Compat to false, no more CompatIU. clearInvocations(mWindowManager); clearInvocations(mLayout); - taskInfo = createTaskInfo(/* hasSizeCompat= */ false, - CAMERA_COMPAT_CONTROL_TREATMENT_SUGGESTED); - assertTrue(mWindowManager.updateCompatInfo(taskInfo, newTaskListener, /* canShow= */ true)); - - verify(mLayout).setRestartButtonVisibility(/* show= */ false); + taskInfo = createTaskInfo(/* hasSizeCompat= */ false); + assertFalse(mWindowManager.updateCompatInfo(taskInfo, newTaskListener, + /* canShow= */ true)); // Change has Size Compat to true, shows restart button. clearInvocations(mWindowManager); clearInvocations(mLayout); - taskInfo = createTaskInfo(/* hasSizeCompat= */ true, - CAMERA_COMPAT_CONTROL_TREATMENT_SUGGESTED); - assertTrue(mWindowManager.updateCompatInfo(taskInfo, newTaskListener, /* canShow= */ true)); - - verify(mLayout).setRestartButtonVisibility(/* show= */ true); - - // Change Camera Compat state to dismissed, hide a control. - clearInvocations(mWindowManager); - clearInvocations(mLayout); - taskInfo = createTaskInfo(/* hasSizeCompat= */ true, CAMERA_COMPAT_CONTROL_DISMISSED); + taskInfo = createTaskInfo(/* hasSizeCompat= */ true); assertTrue(mWindowManager.updateCompatInfo(taskInfo, newTaskListener, /* canShow= */ true)); - verify(mLayout).setCameraControlVisibility(/* show= */ false); + verify(mLayout, times(2)).setRestartButtonVisibility(/* show= */ true); // Change task bounds, update position. clearInvocations(mWindowManager); clearInvocations(mLayout); - taskInfo = createTaskInfo(/* hasSizeCompat= */ true, CAMERA_COMPAT_CONTROL_HIDDEN); + taskInfo = createTaskInfo(/* hasSizeCompat= */ true); taskInfo.configuration.windowConfiguration.setBounds(new Rect(0, 1000, 0, 2000)); assertTrue(mWindowManager.updateCompatInfo(taskInfo, newTaskListener, /* canShow= */ true)); @@ -321,7 +245,7 @@ public class CompatUIWindowManagerTest extends ShellTestCase { // Change has Size Compat to false, release layout. clearInvocations(mWindowManager); clearInvocations(mLayout); - taskInfo = createTaskInfo(/* hasSizeCompat= */ false, CAMERA_COMPAT_CONTROL_HIDDEN); + taskInfo = createTaskInfo(/* hasSizeCompat= */ false); assertFalse( mWindowManager.updateCompatInfo(taskInfo, newTaskListener, /* canShow= */ true)); @@ -338,15 +262,14 @@ public class CompatUIWindowManagerTest extends ShellTestCase { // Change topActivityInSizeCompat to false and pass canShow true, layout shouldn't be // inflated clearInvocations(mWindowManager); - TaskInfo taskInfo = createTaskInfo(/* hasSizeCompat= */ false, - CAMERA_COMPAT_CONTROL_HIDDEN); + TaskInfo taskInfo = createTaskInfo(/* hasSizeCompat= */ false); mWindowManager.updateCompatInfo(taskInfo, mTaskListener, /* canShow= */ true); verify(mWindowManager, never()).inflateLayout(); // Change topActivityInSizeCompat to true and pass canShow true, layout should be inflated. clearInvocations(mWindowManager); - taskInfo = createTaskInfo(/* hasSizeCompat= */ true, CAMERA_COMPAT_CONTROL_HIDDEN); + taskInfo = createTaskInfo(/* hasSizeCompat= */ true); mWindowManager.updateCompatInfo(taskInfo, mTaskListener, /* canShow= */ true); verify(mWindowManager).inflateLayout(); @@ -443,37 +366,6 @@ public class CompatUIWindowManagerTest extends ShellTestCase { @Test @RequiresFlagsDisabled(FLAG_APP_COMPAT_UI_FRAMEWORK) - public void testOnCameraDismissButtonClicked() { - mWindowManager.mCameraCompatControlState = CAMERA_COMPAT_CONTROL_TREATMENT_SUGGESTED; - mWindowManager.createLayout(/* canShow= */ true); - clearInvocations(mLayout); - mWindowManager.onCameraDismissButtonClicked(); - - verifyOnCameraControlStateUpdatedInvokedWith(TASK_ID, CAMERA_COMPAT_CONTROL_DISMISSED); - verify(mLayout).setCameraControlVisibility(/* show= */ false); - } - - @Test - @RequiresFlagsDisabled(FLAG_APP_COMPAT_UI_FRAMEWORK) - public void testOnCameraTreatmentButtonClicked() { - mWindowManager.mCameraCompatControlState = CAMERA_COMPAT_CONTROL_TREATMENT_SUGGESTED; - mWindowManager.createLayout(/* canShow= */ true); - clearInvocations(mLayout); - mWindowManager.onCameraTreatmentButtonClicked(); - - verifyOnCameraControlStateUpdatedInvokedWith(TASK_ID, - CAMERA_COMPAT_CONTROL_TREATMENT_APPLIED); - verify(mLayout).updateCameraTreatmentButton(CAMERA_COMPAT_CONTROL_TREATMENT_APPLIED); - - mWindowManager.onCameraTreatmentButtonClicked(); - - verifyOnCameraControlStateUpdatedInvokedWith(TASK_ID, - CAMERA_COMPAT_CONTROL_TREATMENT_SUGGESTED); - verify(mLayout).updateCameraTreatmentButton(CAMERA_COMPAT_CONTROL_TREATMENT_SUGGESTED); - } - - @Test - @RequiresFlagsDisabled(FLAG_APP_COMPAT_UI_FRAMEWORK) public void testOnRestartButtonClicked() { mWindowManager.onRestartButtonClicked(); @@ -505,22 +397,6 @@ public class CompatUIWindowManagerTest extends ShellTestCase { @Test @RequiresFlagsDisabled(FLAG_APP_COMPAT_UI_FRAMEWORK) - public void testOnCameraControlLongClicked_showHint() { - // Not create hint popup. - mWindowManager.mCameraCompatControlState = CAMERA_COMPAT_CONTROL_TREATMENT_SUGGESTED; - mWindowManager.mCompatUIHintsState.mHasShownCameraCompatHint = true; - mWindowManager.createLayout(/* canShow= */ true); - - verify(mWindowManager).inflateLayout(); - verify(mLayout, never()).setCameraCompatHintVisibility(/* show= */ true); - - mWindowManager.onCameraButtonLongClicked(); - - verify(mLayout).setCameraCompatHintVisibility(/* show= */ true); - } - - @Test - @RequiresFlagsDisabled(FLAG_APP_COMPAT_UI_FRAMEWORK) public void testWhenDockedStateHasChanged_needsToBeRecreated() { ActivityManager.RunningTaskInfo newTaskInfo = new ActivityManager.RunningTaskInfo(); newTaskInfo.configuration.uiMode |= Configuration.UI_MODE_TYPE_DESK; @@ -538,7 +414,7 @@ public class CompatUIWindowManagerTest extends ShellTestCase { mCompatUIConfiguration, mOnRestartButtonClicked); // Simulate rotation of activity in square display - TaskInfo taskInfo = createTaskInfo(true, CAMERA_COMPAT_CONTROL_HIDDEN); + TaskInfo taskInfo = createTaskInfo(true); taskInfo.appCompatTaskInfo.topActivityLetterboxHeight = TASK_HEIGHT; taskInfo.appCompatTaskInfo.topActivityLetterboxWidth = 1850; @@ -567,13 +443,10 @@ public class CompatUIWindowManagerTest extends ShellTestCase { assertTrue(mWindowManager.shouldShowSizeCompatRestartButton(taskInfo)); } - private static TaskInfo createTaskInfo(boolean hasSizeCompat, - @CameraCompatTaskInfo.CameraCompatControlState int cameraCompatControlState) { + private static TaskInfo createTaskInfo(boolean hasSizeCompat) { ActivityManager.RunningTaskInfo taskInfo = new ActivityManager.RunningTaskInfo(); taskInfo.taskId = TASK_ID; taskInfo.appCompatTaskInfo.topActivityInSizeCompat = hasSizeCompat; - taskInfo.appCompatTaskInfo.cameraCompatTaskInfo.cameraCompatControlState = - cameraCompatControlState; taskInfo.configuration.uiMode &= ~Configuration.UI_MODE_TYPE_DESK; // Letterboxed activity that takes half the screen should show size compat restart button taskInfo.appCompatTaskInfo.topActivityLetterboxHeight = 1000; @@ -582,15 +455,4 @@ public class CompatUIWindowManagerTest extends ShellTestCase { taskInfo.configuration.smallestScreenWidthDp = LARGE_SCREEN_SMALLEST_SCREEN_WIDTH_DP; return taskInfo; } - - private void verifyOnCameraControlStateUpdatedInvokedWith(int taskId, int state) { - final ArgumentCaptor<CompatUIEvent> captureValue = ArgumentCaptor.forClass( - CompatUIEvent.class); - verify(mCallback).accept(captureValue.capture()); - final CompatUIEvents.CameraControlStateUpdated compatUIEvent = - (CompatUIEvents.CameraControlStateUpdated) captureValue.getValue(); - Assert.assertEquals((compatUIEvent).getTaskId(), taskId); - Assert.assertEquals((compatUIEvent).getState(), state); - clearInvocations(mCallback); - } } diff --git a/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/compatui/UserAspectRatioSettingsLayoutTest.java b/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/compatui/UserAspectRatioSettingsLayoutTest.java index 3fa21cee0d68..7a641960a2c5 100644 --- a/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/compatui/UserAspectRatioSettingsLayoutTest.java +++ b/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/compatui/UserAspectRatioSettingsLayoutTest.java @@ -16,8 +16,6 @@ package com.android.wm.shell.compatui; -import static android.app.CameraCompatTaskInfo.CAMERA_COMPAT_CONTROL_HIDDEN; - import static com.android.dx.mockito.inline.extended.ExtendedMockito.spyOn; import static com.android.window.flags.Flags.FLAG_APP_COMPAT_UI_FRAMEWORK; @@ -26,7 +24,6 @@ import static org.mockito.Mockito.doReturn; import static org.mockito.Mockito.verify; import android.app.ActivityManager; -import android.app.CameraCompatTaskInfo.CameraCompatControlState; import android.app.TaskInfo; import android.content.ComponentName; import android.platform.test.annotations.RequiresFlagsDisabled; @@ -98,7 +95,7 @@ public class UserAspectRatioSettingsLayoutTest extends ShellTestCase { @Before public void setUp() { MockitoAnnotations.initMocks(this); - mTaskInfo = createTaskInfo(/* hasSizeCompat= */ false, CAMERA_COMPAT_CONTROL_HIDDEN); + mTaskInfo = createTaskInfo(/* hasSizeCompat= */ false); mWindowManager = new UserAspectRatioSettingsWindowManager(mContext, mTaskInfo, mSyncTransactionQueue, mTaskListener, new DisplayLayout(), new CompatUIController.CompatUIHintsState(), @@ -155,13 +152,10 @@ public class UserAspectRatioSettingsLayoutTest extends ShellTestCase { verify(mLayout).setUserAspectRatioSettingsHintVisibility(/* show= */ false); } - private static TaskInfo createTaskInfo(boolean hasSizeCompat, - @CameraCompatControlState int cameraCompatControlState) { + private static TaskInfo createTaskInfo(boolean hasSizeCompat) { ActivityManager.RunningTaskInfo taskInfo = new ActivityManager.RunningTaskInfo(); taskInfo.taskId = TASK_ID; taskInfo.appCompatTaskInfo.topActivityInSizeCompat = hasSizeCompat; - taskInfo.appCompatTaskInfo.cameraCompatTaskInfo.cameraCompatControlState = - cameraCompatControlState; taskInfo.realActivity = new ComponentName("com.mypackage.test", "TestActivity"); return taskInfo; } diff --git a/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/desktopmode/DesktopModeTaskRepositoryTest.kt b/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/desktopmode/DesktopModeTaskRepositoryTest.kt index 0a5672d45f33..d3404f7bd261 100644 --- a/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/desktopmode/DesktopModeTaskRepositoryTest.kt +++ b/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/desktopmode/DesktopModeTaskRepositoryTest.kt @@ -158,8 +158,8 @@ class DesktopModeTaskRepositoryTest : ShellTestCase() { } @Test - fun updateVisibleFreeformTasks_singleVisibleNonClosingTask_updatesTasksCorrectly() { - repo.updateVisibleFreeformTasks(DEFAULT_DISPLAY, taskId = 1, visible = true) + fun updateTaskVisibility_singleVisibleNonClosingTask_updatesTasksCorrectly() { + repo.updateTaskVisibility(DEFAULT_DISPLAY, taskId = 1, visible = true) assertThat(repo.isVisibleTask(1)).isTrue() assertThat(repo.isClosingTask(1)).isFalse() @@ -172,7 +172,7 @@ class DesktopModeTaskRepositoryTest : ShellTestCase() { @Test fun isOnlyVisibleNonClosingTask_singleVisibleClosingTask() { - repo.updateVisibleFreeformTasks(DEFAULT_DISPLAY, taskId = 1, visible = true) + repo.updateTaskVisibility(DEFAULT_DISPLAY, taskId = 1, visible = true) repo.addClosingTask(DEFAULT_DISPLAY, 1) // A visible task that's closing @@ -186,7 +186,7 @@ class DesktopModeTaskRepositoryTest : ShellTestCase() { @Test fun isOnlyVisibleNonClosingTask_singleVisibleMinimizedTask() { - repo.updateVisibleFreeformTasks(DEFAULT_DISPLAY, taskId = 1, visible = true) + repo.updateTaskVisibility(DEFAULT_DISPLAY, taskId = 1, visible = true) repo.minimizeTask(DEFAULT_DISPLAY, 1) // The visible task that's closing @@ -200,8 +200,8 @@ class DesktopModeTaskRepositoryTest : ShellTestCase() { @Test fun isOnlyVisibleNonClosingTask_multipleVisibleNonClosingTasks() { - repo.updateVisibleFreeformTasks(DEFAULT_DISPLAY, taskId = 1, visible = true) - repo.updateVisibleFreeformTasks(DEFAULT_DISPLAY, taskId = 2, visible = true) + repo.updateTaskVisibility(DEFAULT_DISPLAY, taskId = 1, visible = true) + repo.updateTaskVisibility(DEFAULT_DISPLAY, taskId = 2, visible = true) // Not the only task assertThat(repo.isVisibleTask(1)).isTrue() @@ -219,9 +219,9 @@ class DesktopModeTaskRepositoryTest : ShellTestCase() { @Test fun isOnlyVisibleNonClosingTask_multipleDisplays() { - repo.updateVisibleFreeformTasks(DEFAULT_DISPLAY, taskId = 1, visible = true) - repo.updateVisibleFreeformTasks(DEFAULT_DISPLAY, taskId = 2, visible = true) - repo.updateVisibleFreeformTasks(SECOND_DISPLAY, taskId = 3, visible = true) + repo.updateTaskVisibility(DEFAULT_DISPLAY, taskId = 1, visible = true) + repo.updateTaskVisibility(DEFAULT_DISPLAY, taskId = 2, visible = true) + repo.updateTaskVisibility(SECOND_DISPLAY, taskId = 3, visible = true) // Not the only task on DEFAULT_DISPLAY assertThat(repo.isVisibleTask(1)).isTrue() @@ -239,7 +239,7 @@ class DesktopModeTaskRepositoryTest : ShellTestCase() { @Test fun addVisibleTasksListener_notifiesVisibleFreeformTask() { - repo.updateVisibleFreeformTasks(DEFAULT_DISPLAY, taskId = 1, visible = true) + repo.updateTaskVisibility(DEFAULT_DISPLAY, taskId = 1, visible = true) val listener = TestVisibilityListener() val executor = TestShellExecutor() @@ -252,7 +252,7 @@ class DesktopModeTaskRepositoryTest : ShellTestCase() { @Test fun addListener_tasksOnDifferentDisplay_doesNotNotify() { - repo.updateVisibleFreeformTasks(SECOND_DISPLAY, taskId = 1, visible = true) + repo.updateTaskVisibility(SECOND_DISPLAY, taskId = 1, visible = true) val listener = TestVisibilityListener() val executor = TestShellExecutor() repo.addVisibleTasksListener(listener, executor) @@ -264,13 +264,13 @@ class DesktopModeTaskRepositoryTest : ShellTestCase() { } @Test - fun updateVisibleFreeformTasks_addVisibleTasksNotifiesListener() { + fun updateTaskVisibility_addVisibleTasksNotifiesListener() { val listener = TestVisibilityListener() val executor = TestShellExecutor() repo.addVisibleTasksListener(listener, executor) - repo.updateVisibleFreeformTasks(DEFAULT_DISPLAY, taskId = 1, visible = true) - repo.updateVisibleFreeformTasks(DEFAULT_DISPLAY, taskId = 2, visible = true) + repo.updateTaskVisibility(DEFAULT_DISPLAY, taskId = 1, visible = true) + repo.updateTaskVisibility(DEFAULT_DISPLAY, taskId = 2, visible = true) executor.flushAll() assertThat(listener.visibleTasksCountOnDefaultDisplay).isEqualTo(2) @@ -278,12 +278,12 @@ class DesktopModeTaskRepositoryTest : ShellTestCase() { } @Test - fun updateVisibleFreeformTasks_addVisibleTaskNotifiesListenerForThatDisplay() { + fun updateTaskVisibility_addVisibleTaskNotifiesListenerForThatDisplay() { val listener = TestVisibilityListener() val executor = TestShellExecutor() repo.addVisibleTasksListener(listener, executor) - repo.updateVisibleFreeformTasks(DEFAULT_DISPLAY, taskId = 1, visible = true) + repo.updateTaskVisibility(DEFAULT_DISPLAY, taskId = 1, visible = true) executor.flushAll() assertThat(listener.visibleTasksCountOnDefaultDisplay).isEqualTo(1) @@ -291,7 +291,7 @@ class DesktopModeTaskRepositoryTest : ShellTestCase() { assertThat(listener.visibleTasksCountOnSecondaryDisplay).isEqualTo(0) assertThat(listener.visibleChangesOnSecondaryDisplay).isEqualTo(0) - repo.updateVisibleFreeformTasks(displayId = 1, taskId = 2, visible = true) + repo.updateTaskVisibility(displayId = 1, taskId = 2, visible = true) executor.flushAll() // Listener for secondary display is notified @@ -302,17 +302,17 @@ class DesktopModeTaskRepositoryTest : ShellTestCase() { } @Test - fun updateVisibleFreeformTasks_taskOnDefaultBecomesVisibleOnSecondDisplay_listenersNotified() { + fun updateTaskVisibility_taskOnDefaultBecomesVisibleOnSecondDisplay_listenersNotified() { val listener = TestVisibilityListener() val executor = TestShellExecutor() repo.addVisibleTasksListener(listener, executor) - repo.updateVisibleFreeformTasks(DEFAULT_DISPLAY, taskId = 1, visible = true) + repo.updateTaskVisibility(DEFAULT_DISPLAY, taskId = 1, visible = true) executor.flushAll() assertThat(listener.visibleTasksCountOnDefaultDisplay).isEqualTo(1) // Mark task 1 visible on secondary display - repo.updateVisibleFreeformTasks(displayId = 1, taskId = 1, visible = true) + repo.updateTaskVisibility(displayId = 1, taskId = 1, visible = true) executor.flushAll() // Default display should have 2 calls @@ -327,22 +327,22 @@ class DesktopModeTaskRepositoryTest : ShellTestCase() { } @Test - fun updateVisibleFreeformTasks_removeVisibleTasksNotifiesListener() { + fun updateTaskVisibility_removeVisibleTasksNotifiesListener() { val listener = TestVisibilityListener() val executor = TestShellExecutor() repo.addVisibleTasksListener(listener, executor) - repo.updateVisibleFreeformTasks(DEFAULT_DISPLAY, taskId = 1, visible = true) - repo.updateVisibleFreeformTasks(DEFAULT_DISPLAY, taskId = 2, visible = true) + repo.updateTaskVisibility(DEFAULT_DISPLAY, taskId = 1, visible = true) + repo.updateTaskVisibility(DEFAULT_DISPLAY, taskId = 2, visible = true) executor.flushAll() assertThat(listener.visibleTasksCountOnDefaultDisplay).isEqualTo(2) - repo.updateVisibleFreeformTasks(DEFAULT_DISPLAY, taskId = 1, visible = false) + repo.updateTaskVisibility(DEFAULT_DISPLAY, taskId = 1, visible = false) executor.flushAll() assertThat(listener.visibleChangesOnDefaultDisplay).isEqualTo(3) - repo.updateVisibleFreeformTasks(DEFAULT_DISPLAY, taskId = 2, visible = false) + repo.updateTaskVisibility(DEFAULT_DISPLAY, taskId = 2, visible = false) executor.flushAll() assertThat(listener.visibleTasksCountOnDefaultDisplay).isEqualTo(0) @@ -354,17 +354,17 @@ class DesktopModeTaskRepositoryTest : ShellTestCase() { * This tests that task is removed from the last parent display when it vanishes. */ @Test - fun updateVisibleFreeformTasks_removeVisibleTasksRemovesTaskWithInvalidDisplay() { + fun updateTaskVisibility_removeVisibleTasksRemovesTaskWithInvalidDisplay() { val listener = TestVisibilityListener() val executor = TestShellExecutor() repo.addVisibleTasksListener(listener, executor) - repo.updateVisibleFreeformTasks(DEFAULT_DISPLAY, taskId = 1, visible = true) - repo.updateVisibleFreeformTasks(DEFAULT_DISPLAY, taskId = 2, visible = true) + repo.updateTaskVisibility(DEFAULT_DISPLAY, taskId = 1, visible = true) + repo.updateTaskVisibility(DEFAULT_DISPLAY, taskId = 2, visible = true) executor.flushAll() assertThat(listener.visibleTasksCountOnDefaultDisplay).isEqualTo(2) - repo.updateVisibleFreeformTasks(INVALID_DISPLAY, taskId = 1, visible = false) + repo.updateTaskVisibility(INVALID_DISPLAY, taskId = 1, visible = false) executor.flushAll() assertThat(listener.visibleChangesOnDefaultDisplay).isEqualTo(3) @@ -377,30 +377,30 @@ class DesktopModeTaskRepositoryTest : ShellTestCase() { assertThat(repo.getVisibleTaskCount(DEFAULT_DISPLAY)).isEqualTo(0) // New task increments count to 1 - repo.updateVisibleFreeformTasks(DEFAULT_DISPLAY, taskId = 1, visible = true) + repo.updateTaskVisibility(DEFAULT_DISPLAY, taskId = 1, visible = true) assertThat(repo.getVisibleTaskCount(DEFAULT_DISPLAY)).isEqualTo(1) // Visibility update to same task does not increase count - repo.updateVisibleFreeformTasks(DEFAULT_DISPLAY, taskId = 1, visible = true) + repo.updateTaskVisibility(DEFAULT_DISPLAY, taskId = 1, visible = true) assertThat(repo.getVisibleTaskCount(DEFAULT_DISPLAY)).isEqualTo(1) // Second task visible increments count - repo.updateVisibleFreeformTasks(DEFAULT_DISPLAY, taskId = 2, visible = true) + repo.updateTaskVisibility(DEFAULT_DISPLAY, taskId = 2, visible = true) assertThat(repo.getVisibleTaskCount(DEFAULT_DISPLAY)).isEqualTo(2) // Hiding a task decrements count - repo.updateVisibleFreeformTasks(DEFAULT_DISPLAY, taskId = 1, visible = false) + repo.updateTaskVisibility(DEFAULT_DISPLAY, taskId = 1, visible = false) assertThat(repo.getVisibleTaskCount(DEFAULT_DISPLAY)).isEqualTo(1) // Hiding all tasks leaves count at 0 - repo.updateVisibleFreeformTasks(DEFAULT_DISPLAY, taskId = 2, visible = false) + repo.updateTaskVisibility(DEFAULT_DISPLAY, taskId = 2, visible = false) assertThat(repo.getVisibleTaskCount(displayId = 9)).isEqualTo(0) // Hiding a not existing task, count remains at 0 - repo.updateVisibleFreeformTasks(DEFAULT_DISPLAY, taskId = 999, visible = false) + repo.updateTaskVisibility(DEFAULT_DISPLAY, taskId = 999, visible = false) assertThat(repo.getVisibleTaskCount(DEFAULT_DISPLAY)).isEqualTo(0) } @@ -410,32 +410,32 @@ class DesktopModeTaskRepositoryTest : ShellTestCase() { assertThat(repo.getVisibleTaskCount(SECOND_DISPLAY)).isEqualTo(0) // New task on default display increments count for that display only - repo.updateVisibleFreeformTasks(DEFAULT_DISPLAY, taskId = 1, visible = true) + repo.updateTaskVisibility(DEFAULT_DISPLAY, taskId = 1, visible = true) assertThat(repo.getVisibleTaskCount(DEFAULT_DISPLAY)).isEqualTo(1) assertThat(repo.getVisibleTaskCount(SECOND_DISPLAY)).isEqualTo(0) // New task on secondary display, increments count for that display only - repo.updateVisibleFreeformTasks(SECOND_DISPLAY, taskId = 2, visible = true) + repo.updateTaskVisibility(SECOND_DISPLAY, taskId = 2, visible = true) assertThat(repo.getVisibleTaskCount(DEFAULT_DISPLAY)).isEqualTo(1) assertThat(repo.getVisibleTaskCount(SECOND_DISPLAY)).isEqualTo(1) // Marking task visible on another display, updates counts for both displays - repo.updateVisibleFreeformTasks(SECOND_DISPLAY, taskId = 1, visible = true) + repo.updateTaskVisibility(SECOND_DISPLAY, taskId = 1, visible = true) assertThat(repo.getVisibleTaskCount(DEFAULT_DISPLAY)).isEqualTo(0) assertThat(repo.getVisibleTaskCount(SECOND_DISPLAY)).isEqualTo(2) // Marking task that is on secondary display, hidden on default display, does not affect // secondary display - repo.updateVisibleFreeformTasks(DEFAULT_DISPLAY, taskId = 1, visible = false) + repo.updateTaskVisibility(DEFAULT_DISPLAY, taskId = 1, visible = false) assertThat(repo.getVisibleTaskCount(DEFAULT_DISPLAY)).isEqualTo(0) assertThat(repo.getVisibleTaskCount(SECOND_DISPLAY)).isEqualTo(2) // Hiding a task on that display, decrements count - repo.updateVisibleFreeformTasks(SECOND_DISPLAY, taskId = 1, visible = false) + repo.updateTaskVisibility(SECOND_DISPLAY, taskId = 1, visible = false) assertThat(repo.getVisibleTaskCount(DEFAULT_DISPLAY)).isEqualTo(0) assertThat(repo.getVisibleTaskCount(SECOND_DISPLAY)).isEqualTo(1) @@ -468,8 +468,65 @@ class DesktopModeTaskRepositoryTest : ShellTestCase() { } @Test + fun addOrMoveFreeformTaskToTop_taskIsMinimized_unminimizesTask() { + repo.addOrMoveFreeformTaskToTop(DEFAULT_DISPLAY, 5) + repo.addOrMoveFreeformTaskToTop(DEFAULT_DISPLAY, 6) + repo.addOrMoveFreeformTaskToTop(DEFAULT_DISPLAY, 7) + repo.minimizeTask(displayId = 0, taskId = 6) + + val tasks = repo.getFreeformTasksInZOrder(DEFAULT_DISPLAY) + assertThat(tasks).containsExactly(7, 6, 5).inOrder() + assertThat(repo.isMinimizedTask(taskId = 6)).isTrue() + } + + @Test + fun addOrMoveFreeformTaskToTop_taskIsUnminimized_noop() { + repo.addOrMoveFreeformTaskToTop(DEFAULT_DISPLAY, 5) + repo.addOrMoveFreeformTaskToTop(DEFAULT_DISPLAY, 6) + repo.addOrMoveFreeformTaskToTop(DEFAULT_DISPLAY, 7) + + val tasks = repo.getFreeformTasksInZOrder(DEFAULT_DISPLAY) + assertThat(tasks).containsExactly(7, 6, 5).inOrder() + assertThat(repo.isMinimizedTask(taskId = 6)).isFalse() + } + + @Test + fun removeFreeformTask_invalidDisplay_removesTaskFromFreeformTasks() { + repo.addOrMoveFreeformTaskToTop(DEFAULT_DISPLAY, taskId = 1) + + repo.removeFreeformTask(INVALID_DISPLAY, taskId = 1) + + val invalidDisplayTasks = repo.getFreeformTasksInZOrder(INVALID_DISPLAY) + assertThat(invalidDisplayTasks).isEmpty() + val validDisplayTasks = repo.getFreeformTasksInZOrder(DEFAULT_DISPLAY) + assertThat(validDisplayTasks).isEmpty() + } + + @Test + fun removeFreeformTask_validDisplay_removesTaskFromFreeformTasks() { + repo.addOrMoveFreeformTaskToTop(DEFAULT_DISPLAY, taskId = 1) + + repo.removeFreeformTask(DEFAULT_DISPLAY, taskId = 1) + + val tasks = repo.getFreeformTasksInZOrder(DEFAULT_DISPLAY) + assertThat(tasks).isEmpty() + } + + @Test + fun removeFreeformTask_validDisplay_differentDisplay_doesNotRemovesTask() { + repo.addOrMoveFreeformTaskToTop(DEFAULT_DISPLAY, taskId = 1) + + repo.removeFreeformTask(SECOND_DISPLAY, taskId = 1) + + val tasks = repo.getFreeformTasksInZOrder(DEFAULT_DISPLAY) + assertThat(tasks).containsExactly(1) + } + + @Test fun removeFreeformTask_removesTaskBoundsBeforeMaximize() { val taskId = 1 + repo.addActiveTask(THIRD_DISPLAY, taskId) + repo.addOrMoveFreeformTaskToTop(THIRD_DISPLAY, taskId) repo.saveBoundsBeforeMaximize(taskId, Rect(0, 0, 200, 200)) repo.removeFreeformTask(THIRD_DISPLAY, taskId) @@ -478,6 +535,43 @@ class DesktopModeTaskRepositoryTest : ShellTestCase() { } @Test + fun removeFreeformTask_removesActiveTask() { + val taskId = 1 + val listener = TestListener() + repo.addActiveTaskListener(listener) + repo.addActiveTask(DEFAULT_DISPLAY, taskId) + repo.addOrMoveFreeformTaskToTop(DEFAULT_DISPLAY, taskId) + + repo.removeFreeformTask(THIRD_DISPLAY, taskId) + + assertThat(repo.isActiveTask(taskId)).isFalse() + assertThat(listener.activeChangesOnDefaultDisplay).isEqualTo(2) + } + + @Test + fun removeFreeformTask_unminimizesTask() { + val taskId = 1 + repo.addActiveTask(DEFAULT_DISPLAY, taskId) + repo.addOrMoveFreeformTaskToTop(DEFAULT_DISPLAY, taskId) + repo.minimizeTask(DEFAULT_DISPLAY, taskId) + + repo.removeFreeformTask(DEFAULT_DISPLAY, taskId) + + assertThat(repo.isMinimizedTask(taskId)).isFalse() + } + + @Test + fun removeFreeformTask_updatesTaskVisibility() { + val taskId = 1 + repo.addActiveTask(DEFAULT_DISPLAY, taskId) + repo.addOrMoveFreeformTaskToTop(DEFAULT_DISPLAY, taskId) + + repo.removeFreeformTask(THIRD_DISPLAY, taskId) + + assertThat(repo.isVisibleTask(taskId)).isFalse() + } + + @Test fun saveBoundsBeforeMaximize_boundsSavedByTaskId() { val taskId = 1 val bounds = Rect(0, 0, 200, 200) @@ -537,9 +631,9 @@ class DesktopModeTaskRepositoryTest : ShellTestCase() { @Test - fun updateVisibleFreeformTasks_minimizedTaskBecomesVisible_unminimizesTask() { + fun updateTaskVisibility_minimizedTaskBecomesVisible_unminimizesTask() { repo.minimizeTask(displayId = 10, taskId = 2) - repo.updateVisibleFreeformTasks(displayId = 10, taskId = 2, visible = true) + repo.updateTaskVisibility(displayId = 10, taskId = 2, visible = true) val isMinimizedTask = repo.isMinimizedTask(taskId = 2) diff --git a/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/desktopmode/DesktopModeVisualIndicatorTest.kt b/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/desktopmode/DesktopModeVisualIndicatorTest.kt index bd39aa6ace42..2dea43b508ae 100644 --- a/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/desktopmode/DesktopModeVisualIndicatorTest.kt +++ b/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/desktopmode/DesktopModeVisualIndicatorTest.kt @@ -61,20 +61,23 @@ class DesktopModeVisualIndicatorTest : ShellTestCase() { @Test fun testFullscreenRegionCalculation() { - val transitionHeight = context.resources.getDimensionPixelSize( - R.dimen.desktop_mode_fullscreen_from_desktop_height) - val fromFreeformWidth = mContext.resources.getDimensionPixelSize( - R.dimen.desktop_mode_fullscreen_from_desktop_width - ) var testRegion = visualIndicator.calculateFullscreenRegion(displayLayout, WINDOWING_MODE_FULLSCREEN, CAPTION_HEIGHT) assertThat(testRegion.bounds).isEqualTo(Rect(0, -50, 2400, 2 * STABLE_INSETS.top)) testRegion = visualIndicator.calculateFullscreenRegion(displayLayout, WINDOWING_MODE_FREEFORM, CAPTION_HEIGHT) + + val transitionHeight = context.resources.getDimensionPixelSize( + R.dimen.desktop_mode_transition_region_thickness) + val toFullscreenScale = mContext.resources.getFloat( + R.dimen.desktop_mode_fullscreen_region_scale + ) + val toFullscreenWidth = displayLayout.width() * toFullscreenScale + assertThat(testRegion.bounds).isEqualTo(Rect( - DISPLAY_BOUNDS.width() / 2 - fromFreeformWidth / 2, + (DISPLAY_BOUNDS.width() / 2f - toFullscreenWidth / 2f).toInt(), -50, - DISPLAY_BOUNDS.width() / 2 + fromFreeformWidth / 2, + (DISPLAY_BOUNDS.width() / 2f + toFullscreenWidth / 2f).toInt(), transitionHeight)) testRegion = visualIndicator.calculateFullscreenRegion(displayLayout, WINDOWING_MODE_MULTI_WINDOW, CAPTION_HEIGHT) diff --git a/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/desktopmode/DesktopTasksControllerTest.kt b/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/desktopmode/DesktopTasksControllerTest.kt index e66018f26d46..871f61245dc5 100644 --- a/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/desktopmode/DesktopTasksControllerTest.kt +++ b/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/desktopmode/DesktopTasksControllerTest.kt @@ -43,6 +43,7 @@ import android.platform.test.annotations.EnableFlags import android.platform.test.flag.junit.SetFlagsRule import android.testing.AndroidTestingRunner import android.view.Display.DEFAULT_DISPLAY +import android.view.Gravity import android.view.SurfaceControl import android.view.WindowManager import android.view.WindowManager.TRANSIT_CHANGE @@ -70,6 +71,7 @@ import com.android.internal.jank.InteractionJankMonitor import com.android.window.flags.Flags import com.android.window.flags.Flags.FLAG_ENABLE_DESKTOP_WINDOWING_MODE import com.android.wm.shell.MockToken +import com.android.wm.shell.R import com.android.wm.shell.RootTaskDisplayAreaOrganizer import com.android.wm.shell.ShellTaskOrganizer import com.android.wm.shell.ShellTestCase @@ -174,7 +176,7 @@ class DesktopTasksControllerTest : ShellTestCase() { private lateinit var mockitoSession: StaticMockitoSession private lateinit var controller: DesktopTasksController private lateinit var shellInit: ShellInit - private lateinit var desktopModeTaskRepository: DesktopModeTaskRepository + private lateinit var taskRepository: DesktopModeTaskRepository private lateinit var desktopTasksLimiter: DesktopTasksLimiter private lateinit var recentsTransitionStateListener: RecentsTransitionStateListener @@ -185,12 +187,12 @@ class DesktopTasksControllerTest : ShellTestCase() { private val DISPLAY_DIMENSION_SHORT = 1600 private val DISPLAY_DIMENSION_LONG = 2560 - private val DEFAULT_LANDSCAPE_BOUNDS = Rect(320, 200, 2240, 1400) - private val DEFAULT_PORTRAIT_BOUNDS = Rect(200, 320, 1400, 2240) - private val RESIZABLE_LANDSCAPE_BOUNDS = Rect(25, 680, 1575, 1880) - private val RESIZABLE_PORTRAIT_BOUNDS = Rect(680, 200, 1880, 1400) - private val UNRESIZABLE_LANDSCAPE_BOUNDS = Rect(25, 699, 1575, 1861) - private val UNRESIZABLE_PORTRAIT_BOUNDS = Rect(830, 200, 1730, 1400) + private val DEFAULT_LANDSCAPE_BOUNDS = Rect(320, 75, 2240, 1275) + private val DEFAULT_PORTRAIT_BOUNDS = Rect(200, 165, 1400, 2085) + private val RESIZABLE_LANDSCAPE_BOUNDS = Rect(25, 435, 1575, 1635) + private val RESIZABLE_PORTRAIT_BOUNDS = Rect(680, 75, 1880, 1275) + private val UNRESIZABLE_LANDSCAPE_BOUNDS = Rect(25, 449, 1575, 1611) + private val UNRESIZABLE_PORTRAIT_BOUNDS = Rect(830, 75, 1730, 1275) @Before fun setUp() { @@ -202,11 +204,11 @@ class DesktopTasksControllerTest : ShellTestCase() { doReturn(true).`when` { DesktopModeStatus.isDesktopModeSupported(any()) } shellInit = spy(ShellInit(testExecutor)) - desktopModeTaskRepository = DesktopModeTaskRepository() + taskRepository = DesktopModeTaskRepository() desktopTasksLimiter = DesktopTasksLimiter( transitions, - desktopModeTaskRepository, + taskRepository, shellTaskOrganizer, MAX_TASK_LIMIT, ) @@ -250,7 +252,7 @@ class DesktopTasksControllerTest : ShellTestCase() { exitDesktopTransitionHandler, toggleResizeDesktopTaskTransitionHandler, dragToDesktopTransitionHandler, - desktopModeTaskRepository, + taskRepository, desktopModeLoggerTransitionObserver, launchAdjacentController, recentsTransitionHandler, @@ -528,7 +530,7 @@ class DesktopTasksControllerTest : ShellTestCase() { markTaskHidden(freeformTask) markTaskHidden(minimizedTask) - desktopModeTaskRepository.minimizeTask(DEFAULT_DISPLAY, minimizedTask.taskId) + taskRepository.minimizeTask(DEFAULT_DISPLAY, minimizedTask.taskId) controller.showDesktopApps(DEFAULT_DISPLAY, RemoteTransition(TestRemoteTransition())) val wct = getLatestWct(type = TRANSIT_TO_FRONT, handlerClass = OneShotRemoteHandler::class.java) @@ -547,7 +549,7 @@ class DesktopTasksControllerTest : ShellTestCase() { markTaskHidden(freeformTask) markTaskHidden(minimizedTask) - desktopModeTaskRepository.minimizeTask(DEFAULT_DISPLAY, minimizedTask.taskId) + taskRepository.minimizeTask(DEFAULT_DISPLAY, minimizedTask.taskId) controller.showDesktopApps(DEFAULT_DISPLAY, RemoteTransition(TestRemoteTransition())) val wct = getLatestWct(type = TRANSIT_TO_FRONT, handlerClass = OneShotRemoteHandler::class.java) @@ -590,6 +592,161 @@ class DesktopTasksControllerTest : ShellTestCase() { } @Test + fun addMoveToDesktopChanges_gravityLeft_noBoundsApplied() { + setUpLandscapeDisplay() + val task = setUpFullscreenTask(gravity = Gravity.LEFT) + val wct = WindowContainerTransaction() + controller.addMoveToDesktopChanges(wct, task) + + val finalBounds = findBoundsChange(wct, task) + assertThat(finalBounds).isEqualTo(Rect()) + } + + @Test + fun addMoveToDesktopChanges_gravityRight_noBoundsApplied() { + setUpLandscapeDisplay() + val task = setUpFullscreenTask(gravity = Gravity.RIGHT) + val wct = WindowContainerTransaction() + controller.addMoveToDesktopChanges(wct, task) + + val finalBounds = findBoundsChange(wct, task) + assertThat(finalBounds).isEqualTo(Rect()) + } + + @Test + fun addMoveToDesktopChanges_gravityTop_noBoundsApplied() { + setUpLandscapeDisplay() + val task = setUpFullscreenTask(gravity = Gravity.TOP) + val wct = WindowContainerTransaction() + controller.addMoveToDesktopChanges(wct, task) + + val finalBounds = findBoundsChange(wct, task) + assertThat(finalBounds).isEqualTo(Rect()) + } + + @Test + fun addMoveToDesktopChanges_gravityBottom_noBoundsApplied() { + setUpLandscapeDisplay() + val task = setUpFullscreenTask(gravity = Gravity.BOTTOM) + val wct = WindowContainerTransaction() + controller.addMoveToDesktopChanges(wct, task) + + val finalBounds = findBoundsChange(wct, task) + assertThat(finalBounds).isEqualTo(Rect()) + } + + @Test + @EnableFlags(Flags.FLAG_ENABLE_CASCADING_WINDOWS) + fun addMoveToDesktopChanges_positionBottomRight() { + setUpLandscapeDisplay() + val stableBounds = Rect() + displayLayout.getStableBoundsForDesktopMode(stableBounds) + + setUpFreeformTask(bounds = DEFAULT_LANDSCAPE_BOUNDS) + + val task = setUpFullscreenTask() + val wct = WindowContainerTransaction() + controller.addMoveToDesktopChanges(wct, task) + + val finalBounds = findBoundsChange(wct, task) + assertThat(stableBounds.getDesktopTaskPosition(finalBounds!!)) + .isEqualTo(DesktopTaskPosition.BottomRight) + } + + @Test + @EnableFlags(Flags.FLAG_ENABLE_CASCADING_WINDOWS) + fun addMoveToDesktopChanges_positionTopLeft() { + setUpLandscapeDisplay() + val stableBounds = Rect() + displayLayout.getStableBoundsForDesktopMode(stableBounds) + + addFreeformTaskAtPosition(DesktopTaskPosition.BottomRight, stableBounds) + + val task = setUpFullscreenTask() + val wct = WindowContainerTransaction() + controller.addMoveToDesktopChanges(wct, task) + + val finalBounds = findBoundsChange(wct, task) + assertThat(stableBounds.getDesktopTaskPosition(finalBounds!!)) + .isEqualTo(DesktopTaskPosition.TopLeft) + } + + @Test + @EnableFlags(Flags.FLAG_ENABLE_CASCADING_WINDOWS) + fun addMoveToDesktopChanges_positionBottomLeft() { + setUpLandscapeDisplay() + val stableBounds = Rect() + displayLayout.getStableBoundsForDesktopMode(stableBounds) + + addFreeformTaskAtPosition(DesktopTaskPosition.TopLeft, stableBounds) + + val task = setUpFullscreenTask() + val wct = WindowContainerTransaction() + controller.addMoveToDesktopChanges(wct, task) + + val finalBounds = findBoundsChange(wct, task) + assertThat(stableBounds.getDesktopTaskPosition(finalBounds!!)) + .isEqualTo(DesktopTaskPosition.BottomLeft) + } + + @Test + @EnableFlags(Flags.FLAG_ENABLE_CASCADING_WINDOWS) + fun addMoveToDesktopChanges_positionTopRight() { + setUpLandscapeDisplay() + val stableBounds = Rect() + displayLayout.getStableBoundsForDesktopMode(stableBounds) + + addFreeformTaskAtPosition(DesktopTaskPosition.BottomLeft, stableBounds) + + val task = setUpFullscreenTask() + val wct = WindowContainerTransaction() + controller.addMoveToDesktopChanges(wct, task) + + val finalBounds = findBoundsChange(wct, task) + assertThat(stableBounds.getDesktopTaskPosition(finalBounds!!)) + .isEqualTo(DesktopTaskPosition.TopRight) + } + + @Test + @EnableFlags(Flags.FLAG_ENABLE_CASCADING_WINDOWS) + fun addMoveToDesktopChanges_positionResetsToCenter() { + setUpLandscapeDisplay() + val stableBounds = Rect() + displayLayout.getStableBoundsForDesktopMode(stableBounds) + + addFreeformTaskAtPosition(DesktopTaskPosition.TopRight, stableBounds) + + val task = setUpFullscreenTask() + val wct = WindowContainerTransaction() + controller.addMoveToDesktopChanges(wct, task) + + val finalBounds = findBoundsChange(wct, task) + assertThat(stableBounds.getDesktopTaskPosition(finalBounds!!)) + .isEqualTo(DesktopTaskPosition.Center) + } + + @Test + @EnableFlags(Flags.FLAG_ENABLE_CASCADING_WINDOWS) + fun addMoveToDesktopChanges_defaultToCenterIfFree() { + setUpLandscapeDisplay() + val stableBounds = Rect() + displayLayout.getStableBoundsForDesktopMode(stableBounds) + + val minTouchTarget = context.resources.getDimensionPixelSize( + R.dimen.freeform_required_visible_empty_space_in_header) + addFreeformTaskAtPosition(DesktopTaskPosition.Center, stableBounds, + Rect(0, 0, 1600, 1200), Point(0, minTouchTarget + 1)) + + val task = setUpFullscreenTask() + val wct = WindowContainerTransaction() + controller.addMoveToDesktopChanges(wct, task) + + val finalBounds = findBoundsChange(wct, task) + assertThat(stableBounds.getDesktopTaskPosition(finalBounds!!)) + .isEqualTo(DesktopTaskPosition.Center) + } + + @Test fun moveToDesktop_tdaFullscreen_windowingModeSetToFreeform() { val task = setUpFullscreenTask() val tda = rootTaskDisplayAreaOrganizer.getDisplayAreaInfo(DEFAULT_DISPLAY)!! @@ -838,7 +995,7 @@ class DesktopTasksControllerTest : ShellTestCase() { val task = setUpFreeformTask() val wallpaperToken = MockToken().token() - desktopModeTaskRepository.wallpaperActivityToken = wallpaperToken + taskRepository.wallpaperActivityToken = wallpaperToken assertNotNull(rootTaskDisplayAreaOrganizer.getDisplayAreaInfo(DEFAULT_DISPLAY)) .configuration.windowConfiguration.windowingMode = WINDOWING_MODE_FULLSCREEN @@ -867,7 +1024,7 @@ class DesktopTasksControllerTest : ShellTestCase() { val task = setUpFreeformTask() val wallpaperToken = MockToken().token() - desktopModeTaskRepository.wallpaperActivityToken = wallpaperToken + taskRepository.wallpaperActivityToken = wallpaperToken assertNotNull(rootTaskDisplayAreaOrganizer.getDisplayAreaInfo(DEFAULT_DISPLAY)) .configuration.windowConfiguration.windowingMode = WINDOWING_MODE_FREEFORM @@ -887,7 +1044,7 @@ class DesktopTasksControllerTest : ShellTestCase() { setUpFreeformTask() val wallpaperToken = MockToken().token() - desktopModeTaskRepository.wallpaperActivityToken = wallpaperToken + taskRepository.wallpaperActivityToken = wallpaperToken assertNotNull(rootTaskDisplayAreaOrganizer.getDisplayAreaInfo(DEFAULT_DISPLAY)) .configuration.windowConfiguration.windowingMode = WINDOWING_MODE_FULLSCREEN @@ -1028,7 +1185,7 @@ class DesktopTasksControllerTest : ShellTestCase() { fun onDesktopWindowClose_singleActiveTask_hasWallpaperActivityToken() { val task = setUpFreeformTask() val wallpaperToken = MockToken().token() - desktopModeTaskRepository.wallpaperActivityToken = wallpaperToken + taskRepository.wallpaperActivityToken = wallpaperToken val wct = WindowContainerTransaction() controller.onDesktopWindowClose(wct, displayId = DEFAULT_DISPLAY, taskId = task.taskId) @@ -1040,8 +1197,8 @@ class DesktopTasksControllerTest : ShellTestCase() { fun onDesktopWindowClose_singleActiveTask_isClosing() { val task = setUpFreeformTask() val wallpaperToken = MockToken().token() - desktopModeTaskRepository.wallpaperActivityToken = wallpaperToken - desktopModeTaskRepository.addClosingTask(DEFAULT_DISPLAY, task.taskId) + taskRepository.wallpaperActivityToken = wallpaperToken + taskRepository.addClosingTask(DEFAULT_DISPLAY, task.taskId) val wct = WindowContainerTransaction() controller.onDesktopWindowClose(wct, displayId = DEFAULT_DISPLAY, taskId = task.taskId) @@ -1053,8 +1210,8 @@ class DesktopTasksControllerTest : ShellTestCase() { fun onDesktopWindowClose_singleActiveTask_isMinimized() { val task = setUpFreeformTask() val wallpaperToken = MockToken().token() - desktopModeTaskRepository.wallpaperActivityToken = wallpaperToken - desktopModeTaskRepository.minimizeTask(DEFAULT_DISPLAY, task.taskId) + taskRepository.wallpaperActivityToken = wallpaperToken + taskRepository.minimizeTask(DEFAULT_DISPLAY, task.taskId) val wct = WindowContainerTransaction() controller.onDesktopWindowClose(wct, displayId = DEFAULT_DISPLAY, taskId = task.taskId) @@ -1067,7 +1224,7 @@ class DesktopTasksControllerTest : ShellTestCase() { val task1 = setUpFreeformTask() setUpFreeformTask() val wallpaperToken = MockToken().token() - desktopModeTaskRepository.wallpaperActivityToken = wallpaperToken + taskRepository.wallpaperActivityToken = wallpaperToken val wct = WindowContainerTransaction() controller.onDesktopWindowClose(wct, displayId = DEFAULT_DISPLAY, taskId = task1.taskId) @@ -1080,8 +1237,8 @@ class DesktopTasksControllerTest : ShellTestCase() { val task1 = setUpFreeformTask() val task2 = setUpFreeformTask() val wallpaperToken = MockToken().token() - desktopModeTaskRepository.wallpaperActivityToken = wallpaperToken - desktopModeTaskRepository.addClosingTask(DEFAULT_DISPLAY, task2.taskId) + taskRepository.wallpaperActivityToken = wallpaperToken + taskRepository.addClosingTask(DEFAULT_DISPLAY, task2.taskId) val wct = WindowContainerTransaction() controller.onDesktopWindowClose(wct, displayId = DEFAULT_DISPLAY, taskId = task1.taskId) @@ -1094,8 +1251,8 @@ class DesktopTasksControllerTest : ShellTestCase() { val task1 = setUpFreeformTask() val task2 = setUpFreeformTask() val wallpaperToken = MockToken().token() - desktopModeTaskRepository.wallpaperActivityToken = wallpaperToken - desktopModeTaskRepository.minimizeTask(DEFAULT_DISPLAY, task2.taskId) + taskRepository.wallpaperActivityToken = wallpaperToken + taskRepository.minimizeTask(DEFAULT_DISPLAY, task2.taskId) val wct = WindowContainerTransaction() controller.onDesktopWindowClose(wct, displayId = DEFAULT_DISPLAY, taskId = task1.taskId) @@ -1501,7 +1658,7 @@ class DesktopTasksControllerTest : ShellTestCase() { fun handleRequest_backTransition_singleTaskWithToken_noWallpaper_noBackNav_doesNotHandle() { val task = setUpFreeformTask() - desktopModeTaskRepository.wallpaperActivityToken = MockToken().token() + taskRepository.wallpaperActivityToken = MockToken().token() val result = controller.handleRequest(Binder(), createTransition(task, type = TRANSIT_TO_BACK)) assertNull(result, "Should not handle request") @@ -1516,7 +1673,7 @@ class DesktopTasksControllerTest : ShellTestCase() { val task = setUpFreeformTask() val wallpaperToken = MockToken().token() - desktopModeTaskRepository.wallpaperActivityToken = wallpaperToken + taskRepository.wallpaperActivityToken = wallpaperToken val result = controller.handleRequest(Binder(), createTransition(task, type = TRANSIT_TO_BACK)) // Should create remove wallpaper transaction @@ -1531,7 +1688,7 @@ class DesktopTasksControllerTest : ShellTestCase() { val task = setUpFreeformTask() val wallpaperToken = MockToken().token() - desktopModeTaskRepository.wallpaperActivityToken = wallpaperToken + taskRepository.wallpaperActivityToken = wallpaperToken val result = controller.handleRequest(Binder(), createTransition(task, type = TRANSIT_TO_BACK)) // Should create remove wallpaper transaction @@ -1547,7 +1704,7 @@ class DesktopTasksControllerTest : ShellTestCase() { val task1 = setUpFreeformTask() setUpFreeformTask() - desktopModeTaskRepository.wallpaperActivityToken = MockToken().token() + taskRepository.wallpaperActivityToken = MockToken().token() val result = controller.handleRequest(Binder(), createTransition(task1, type = TRANSIT_TO_BACK)) assertNull(result, "Should not handle request") @@ -1562,7 +1719,7 @@ class DesktopTasksControllerTest : ShellTestCase() { val task1 = setUpFreeformTask() setUpFreeformTask() - desktopModeTaskRepository.wallpaperActivityToken = MockToken().token() + taskRepository.wallpaperActivityToken = MockToken().token() val result = controller.handleRequest(Binder(), createTransition(task1, type = TRANSIT_TO_BACK)) assertNotNull(result, "Should handle request").assertRemoveAt(index = 0, task1.token) @@ -1575,7 +1732,7 @@ class DesktopTasksControllerTest : ShellTestCase() { val task1 = setUpFreeformTask() setUpFreeformTask() - desktopModeTaskRepository.wallpaperActivityToken = MockToken().token() + taskRepository.wallpaperActivityToken = MockToken().token() val result = controller.handleRequest(Binder(), createTransition(task1, type = TRANSIT_TO_BACK)) assertNull(result, "Should not handle request") @@ -1591,8 +1748,8 @@ class DesktopTasksControllerTest : ShellTestCase() { val task2 = setUpFreeformTask(displayId = DEFAULT_DISPLAY) val wallpaperToken = MockToken().token() - desktopModeTaskRepository.wallpaperActivityToken = wallpaperToken - desktopModeTaskRepository.addClosingTask(displayId = DEFAULT_DISPLAY, taskId = task2.taskId) + taskRepository.wallpaperActivityToken = wallpaperToken + taskRepository.addClosingTask(displayId = DEFAULT_DISPLAY, taskId = task2.taskId) val result = controller.handleRequest(Binder(), createTransition(task1, type = TRANSIT_TO_BACK)) // Should create remove wallpaper transaction @@ -1608,8 +1765,8 @@ class DesktopTasksControllerTest : ShellTestCase() { val task2 = setUpFreeformTask(displayId = DEFAULT_DISPLAY) val wallpaperToken = MockToken().token() - desktopModeTaskRepository.wallpaperActivityToken = wallpaperToken - desktopModeTaskRepository.addClosingTask(displayId = DEFAULT_DISPLAY, taskId = task2.taskId) + taskRepository.wallpaperActivityToken = wallpaperToken + taskRepository.addClosingTask(displayId = DEFAULT_DISPLAY, taskId = task2.taskId) val result = controller.handleRequest(Binder(), createTransition(task1, type = TRANSIT_TO_BACK)) // Should create remove wallpaper transaction @@ -1626,8 +1783,8 @@ class DesktopTasksControllerTest : ShellTestCase() { val task2 = setUpFreeformTask(displayId = DEFAULT_DISPLAY) val wallpaperToken = MockToken().token() - desktopModeTaskRepository.wallpaperActivityToken = wallpaperToken - desktopModeTaskRepository.minimizeTask(displayId = DEFAULT_DISPLAY, taskId = task2.taskId) + taskRepository.wallpaperActivityToken = wallpaperToken + taskRepository.minimizeTask(displayId = DEFAULT_DISPLAY, taskId = task2.taskId) val result = controller.handleRequest(Binder(), createTransition(task1, type = TRANSIT_TO_BACK)) // Should create remove wallpaper transaction @@ -1643,8 +1800,8 @@ class DesktopTasksControllerTest : ShellTestCase() { val task2 = setUpFreeformTask(displayId = DEFAULT_DISPLAY) val wallpaperToken = MockToken().token() - desktopModeTaskRepository.wallpaperActivityToken = wallpaperToken - desktopModeTaskRepository.minimizeTask(displayId = DEFAULT_DISPLAY, taskId = task2.taskId) + taskRepository.wallpaperActivityToken = wallpaperToken + taskRepository.minimizeTask(displayId = DEFAULT_DISPLAY, taskId = task2.taskId) val result = controller.handleRequest(Binder(), createTransition(task1, type = TRANSIT_TO_BACK)) // Should create remove wallpaper transaction @@ -1661,11 +1818,11 @@ class DesktopTasksControllerTest : ShellTestCase() { val task2 = setUpFreeformTask(displayId = DEFAULT_DISPLAY) val wallpaperToken = MockToken().token() - desktopModeTaskRepository.wallpaperActivityToken = wallpaperToken - desktopModeTaskRepository.minimizeTask(displayId = DEFAULT_DISPLAY, taskId = task2.taskId) + taskRepository.wallpaperActivityToken = wallpaperToken + taskRepository.minimizeTask(displayId = DEFAULT_DISPLAY, taskId = task2.taskId) // Task is being minimized so mark it as not visible. - desktopModeTaskRepository - .updateVisibleFreeformTasks(displayId = DEFAULT_DISPLAY, task2.taskId, false) + taskRepository + .updateTaskVisibility(displayId = DEFAULT_DISPLAY, task2.taskId, false) val result = controller.handleRequest(Binder(), createTransition(task2, type = TRANSIT_TO_BACK)) assertNull(result, "Should not handle request") @@ -1716,7 +1873,7 @@ class DesktopTasksControllerTest : ShellTestCase() { fun handleRequest_closeTransition_singleTaskWithToken_noWallpaper_noBackNav_doesNotHandle() { val task = setUpFreeformTask() - desktopModeTaskRepository.wallpaperActivityToken = MockToken().token() + taskRepository.wallpaperActivityToken = MockToken().token() val result = controller.handleRequest(Binder(), createTransition(task, type = TRANSIT_CLOSE)) assertNull(result, "Should not handle request") @@ -1731,7 +1888,7 @@ class DesktopTasksControllerTest : ShellTestCase() { val task = setUpFreeformTask() val wallpaperToken = MockToken().token() - desktopModeTaskRepository.wallpaperActivityToken = wallpaperToken + taskRepository.wallpaperActivityToken = wallpaperToken val result = controller.handleRequest(Binder(), createTransition(task, type = TRANSIT_CLOSE)) // Should create remove wallpaper transaction @@ -1746,7 +1903,7 @@ class DesktopTasksControllerTest : ShellTestCase() { val task = setUpFreeformTask() val wallpaperToken = MockToken().token() - desktopModeTaskRepository.wallpaperActivityToken = wallpaperToken + taskRepository.wallpaperActivityToken = wallpaperToken val result = controller.handleRequest(Binder(), createTransition(task, type = TRANSIT_CLOSE)) // Should create remove wallpaper transaction @@ -1762,7 +1919,7 @@ class DesktopTasksControllerTest : ShellTestCase() { val task1 = setUpFreeformTask() setUpFreeformTask() - desktopModeTaskRepository.wallpaperActivityToken = MockToken().token() + taskRepository.wallpaperActivityToken = MockToken().token() val result = controller.handleRequest(Binder(), createTransition(task1, type = TRANSIT_CLOSE)) assertNull(result, "Should not handle request") @@ -1777,7 +1934,7 @@ class DesktopTasksControllerTest : ShellTestCase() { val task1 = setUpFreeformTask() setUpFreeformTask() - desktopModeTaskRepository.wallpaperActivityToken = MockToken().token() + taskRepository.wallpaperActivityToken = MockToken().token() val result = controller.handleRequest(Binder(), createTransition(task1, type = TRANSIT_CLOSE)) assertNotNull(result, "Should handle request") @@ -1791,7 +1948,7 @@ class DesktopTasksControllerTest : ShellTestCase() { val task1 = setUpFreeformTask() setUpFreeformTask() - desktopModeTaskRepository.wallpaperActivityToken = MockToken().token() + taskRepository.wallpaperActivityToken = MockToken().token() val result = controller.handleRequest(Binder(), createTransition(task1, type = TRANSIT_CLOSE)) assertNull(result, "Should not handle request") @@ -1807,8 +1964,8 @@ class DesktopTasksControllerTest : ShellTestCase() { val task2 = setUpFreeformTask(displayId = DEFAULT_DISPLAY) val wallpaperToken = MockToken().token() - desktopModeTaskRepository.wallpaperActivityToken = wallpaperToken - desktopModeTaskRepository.addClosingTask(displayId = DEFAULT_DISPLAY, taskId = task2.taskId) + taskRepository.wallpaperActivityToken = wallpaperToken + taskRepository.addClosingTask(displayId = DEFAULT_DISPLAY, taskId = task2.taskId) val result = controller.handleRequest(Binder(), createTransition(task1, type = TRANSIT_CLOSE)) // Should create remove wallpaper transaction @@ -1824,8 +1981,8 @@ class DesktopTasksControllerTest : ShellTestCase() { val task2 = setUpFreeformTask(displayId = DEFAULT_DISPLAY) val wallpaperToken = MockToken().token() - desktopModeTaskRepository.wallpaperActivityToken = wallpaperToken - desktopModeTaskRepository.addClosingTask(displayId = DEFAULT_DISPLAY, taskId = task2.taskId) + taskRepository.wallpaperActivityToken = wallpaperToken + taskRepository.addClosingTask(displayId = DEFAULT_DISPLAY, taskId = task2.taskId) val result = controller.handleRequest(Binder(), createTransition(task1, type = TRANSIT_CLOSE)) // Should create remove wallpaper transaction @@ -1842,8 +1999,8 @@ class DesktopTasksControllerTest : ShellTestCase() { val task2 = setUpFreeformTask(displayId = DEFAULT_DISPLAY) val wallpaperToken = MockToken().token() - desktopModeTaskRepository.wallpaperActivityToken = wallpaperToken - desktopModeTaskRepository.minimizeTask(displayId = DEFAULT_DISPLAY, taskId = task2.taskId) + taskRepository.wallpaperActivityToken = wallpaperToken + taskRepository.minimizeTask(displayId = DEFAULT_DISPLAY, taskId = task2.taskId) val result = controller.handleRequest(Binder(), createTransition(task1, type = TRANSIT_CLOSE)) // Should create remove wallpaper transaction @@ -1859,8 +2016,8 @@ class DesktopTasksControllerTest : ShellTestCase() { val task2 = setUpFreeformTask(displayId = DEFAULT_DISPLAY) val wallpaperToken = MockToken().token() - desktopModeTaskRepository.wallpaperActivityToken = wallpaperToken - desktopModeTaskRepository.minimizeTask(displayId = DEFAULT_DISPLAY, taskId = task2.taskId) + taskRepository.wallpaperActivityToken = wallpaperToken + taskRepository.minimizeTask(displayId = DEFAULT_DISPLAY, taskId = task2.taskId) val result = controller.handleRequest(Binder(), createTransition(task1, type = TRANSIT_CLOSE)) // Should create remove wallpaper transaction @@ -1877,11 +2034,11 @@ class DesktopTasksControllerTest : ShellTestCase() { val task2 = setUpFreeformTask(displayId = DEFAULT_DISPLAY) val wallpaperToken = MockToken().token() - desktopModeTaskRepository.wallpaperActivityToken = wallpaperToken - desktopModeTaskRepository.minimizeTask(displayId = DEFAULT_DISPLAY, taskId = task2.taskId) + taskRepository.wallpaperActivityToken = wallpaperToken + taskRepository.minimizeTask(displayId = DEFAULT_DISPLAY, taskId = task2.taskId) // Task is being minimized so mark it as not visible. - desktopModeTaskRepository - .updateVisibleFreeformTasks(displayId = DEFAULT_DISPLAY, task2.taskId, false) + taskRepository + .updateTaskVisibility(displayId = DEFAULT_DISPLAY, task2.taskId, false) val result = controller.handleRequest(Binder(), createTransition(task2, type = TRANSIT_TO_BACK)) assertNull(result, "Should not handle request") @@ -1975,9 +2132,9 @@ class DesktopTasksControllerTest : ShellTestCase() { task1.isFocused = false task2.isFocused = true task3.isFocused = false - desktopModeTaskRepository.wallpaperActivityToken = wallpaperToken - desktopModeTaskRepository.minimizeTask(DEFAULT_DISPLAY, task1.taskId) - desktopModeTaskRepository.updateVisibleFreeformTasks(DEFAULT_DISPLAY, task3.taskId, + taskRepository.wallpaperActivityToken = wallpaperToken + taskRepository.minimizeTask(DEFAULT_DISPLAY, task1.taskId) + taskRepository.updateTaskVisibility(DEFAULT_DISPLAY, task3.taskId, visible = false) controller.enterFullscreen(DEFAULT_DISPLAY, transitionSource = UNKNOWN) @@ -1998,7 +2155,7 @@ class DesktopTasksControllerTest : ShellTestCase() { task1.isFocused = false task2.isFocused = true task3.isFocused = false - desktopModeTaskRepository.wallpaperActivityToken = wallpaperToken + taskRepository.wallpaperActivityToken = wallpaperToken controller.enterFullscreen(DEFAULT_DISPLAY, transitionSource = UNKNOWN) val wct = getLatestExitDesktopWct() @@ -2247,9 +2404,9 @@ class DesktopTasksControllerTest : ShellTestCase() { task1.isFocused = false task2.isFocused = true task3.isFocused = false - desktopModeTaskRepository.wallpaperActivityToken = wallpaperToken - desktopModeTaskRepository.minimizeTask(DEFAULT_DISPLAY, task1.taskId) - desktopModeTaskRepository.updateVisibleFreeformTasks(DEFAULT_DISPLAY, task3.taskId, + taskRepository.wallpaperActivityToken = wallpaperToken + taskRepository.minimizeTask(DEFAULT_DISPLAY, task1.taskId) + taskRepository.updateTaskVisibility(DEFAULT_DISPLAY, task3.taskId, visible = false) controller.enterSplit(DEFAULT_DISPLAY, leftOrTop = false) @@ -2275,7 +2432,7 @@ class DesktopTasksControllerTest : ShellTestCase() { task1.isFocused = false task2.isFocused = true task3.isFocused = false - desktopModeTaskRepository.wallpaperActivityToken = wallpaperToken + taskRepository.wallpaperActivityToken = wallpaperToken controller.enterSplit(DEFAULT_DISPLAY, leftOrTop = false) @@ -2327,7 +2484,7 @@ class DesktopTasksControllerTest : ShellTestCase() { val task = setUpFreeformTask(DEFAULT_DISPLAY, bounds) controller.toggleDesktopTaskSize(task) - assertThat(desktopModeTaskRepository.removeBoundsBeforeMaximize(task.taskId)).isEqualTo(bounds) + assertThat(taskRepository.removeBoundsBeforeMaximize(task.taskId)).isEqualTo(bounds) } @Test @@ -2400,12 +2557,24 @@ class DesktopTasksControllerTest : ShellTestCase() { controller.toggleDesktopTaskSize(task) // Assert last bounds before maximize removed after use - assertThat(desktopModeTaskRepository.removeBoundsBeforeMaximize(task.taskId)).isNull() + assertThat(taskRepository.removeBoundsBeforeMaximize(task.taskId)).isNull() } private val desktopWallpaperIntent: Intent get() = Intent(context, DesktopWallpaperActivity::class.java) + private fun addFreeformTaskAtPosition( + pos: DesktopTaskPosition, + stableBounds: Rect, + bounds: Rect = DEFAULT_LANDSCAPE_BOUNDS, + offsetPos: Point = Point(0, 0) + ): RunningTaskInfo { + val offset = pos.getTopLeftCoordinates(stableBounds, bounds) + val prevTaskBounds = Rect(bounds) + prevTaskBounds.offsetTo(offset.x + offsetPos.x, offset.y + offsetPos.y) + return setUpFreeformTask(bounds = prevTaskBounds) + } + private fun setUpFreeformTask( displayId: Int = DEFAULT_DISPLAY, bounds: Rect? = null @@ -2414,9 +2583,9 @@ class DesktopTasksControllerTest : ShellTestCase() { val activityInfo = ActivityInfo() task.topActivityInfo = activityInfo whenever(shellTaskOrganizer.getRunningTaskInfo(task.taskId)).thenReturn(task) - desktopModeTaskRepository.addActiveTask(displayId, task.taskId) - desktopModeTaskRepository.updateVisibleFreeformTasks(displayId, task.taskId, visible = true) - desktopModeTaskRepository.addOrMoveFreeformTaskToTop(displayId, task.taskId) + taskRepository.addActiveTask(displayId, task.taskId) + taskRepository.updateTaskVisibility(displayId, task.taskId, visible = true) + taskRepository.addOrMoveFreeformTaskToTop(displayId, task.taskId) runningTasks.add(task) return task } @@ -2434,11 +2603,13 @@ class DesktopTasksControllerTest : ShellTestCase() { windowingMode: Int = WINDOWING_MODE_FULLSCREEN, deviceOrientation: Int = ORIENTATION_LANDSCAPE, screenOrientation: Int = SCREEN_ORIENTATION_UNSPECIFIED, - shouldLetterbox: Boolean = false + shouldLetterbox: Boolean = false, + gravity: Int = Gravity.NO_GRAVITY ): RunningTaskInfo { val task = createFullscreenTask(displayId) val activityInfo = ActivityInfo() activityInfo.screenOrientation = screenOrientation + activityInfo.windowLayout = ActivityInfo.WindowLayout(0, 0F, 0, 0F, gravity, 0, 0) with(task) { topActivityInfo = activityInfo isResizeable = isResizable @@ -2479,11 +2650,23 @@ class DesktopTasksControllerTest : ShellTestCase() { private fun setUpLandscapeDisplay() { whenever(displayLayout.width()).thenReturn(DISPLAY_DIMENSION_LONG) whenever(displayLayout.height()).thenReturn(DISPLAY_DIMENSION_SHORT) + val stableBounds = Rect(0, 0, DISPLAY_DIMENSION_LONG, + DISPLAY_DIMENSION_SHORT - Companion.TASKBAR_FRAME_HEIGHT + ) + whenever(displayLayout.getStableBoundsForDesktopMode(any())).thenAnswer { i -> + (i.arguments.first() as Rect).set(stableBounds) + } } private fun setUpPortraitDisplay() { whenever(displayLayout.width()).thenReturn(DISPLAY_DIMENSION_SHORT) whenever(displayLayout.height()).thenReturn(DISPLAY_DIMENSION_LONG) + val stableBounds = Rect(0, 0, DISPLAY_DIMENSION_SHORT, + DISPLAY_DIMENSION_LONG - Companion.TASKBAR_FRAME_HEIGHT + ) + whenever(displayLayout.getStableBoundsForDesktopMode(any())).thenAnswer { i -> + (i.arguments.first() as Rect).set(stableBounds) + } } private fun setUpSplitScreenTask(displayId: Int = DEFAULT_DISPLAY): RunningTaskInfo { @@ -2495,12 +2678,12 @@ class DesktopTasksControllerTest : ShellTestCase() { } private fun markTaskVisible(task: RunningTaskInfo) { - desktopModeTaskRepository.updateVisibleFreeformTasks( + taskRepository.updateTaskVisibility( task.displayId, task.taskId, visible = true) } private fun markTaskHidden(task: RunningTaskInfo) { - desktopModeTaskRepository.updateVisibleFreeformTasks( + taskRepository.updateTaskVisibility( task.displayId, task.taskId, visible = false) } @@ -2601,6 +2784,7 @@ class DesktopTasksControllerTest : ShellTestCase() { const val SECOND_DISPLAY = 2 val STABLE_BOUNDS = Rect(0, 0, 1000, 1000) const val MAX_TASK_LIMIT = 6 + private const val TASKBAR_FRAME_HEIGHT = 200 } } diff --git a/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/desktopmode/DesktopTasksLimiterTest.kt b/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/desktopmode/DesktopTasksLimiterTest.kt index 70f3bf8828fa..d4a749cc4e29 100644 --- a/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/desktopmode/DesktopTasksLimiterTest.kt +++ b/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/desktopmode/DesktopTasksLimiterTest.kt @@ -358,7 +358,7 @@ class DesktopTasksLimiterTest : ShellTestCase() { } private fun markTaskVisible(task: RunningTaskInfo) { - desktopTaskRepo.updateVisibleFreeformTasks( + desktopTaskRepo.updateTaskVisibility( task.displayId, task.taskId, visible = true @@ -366,7 +366,7 @@ class DesktopTasksLimiterTest : ShellTestCase() { } private fun markTaskHidden(task: RunningTaskInfo) { - desktopTaskRepo.updateVisibleFreeformTasks( + desktopTaskRepo.updateTaskVisibility( task.displayId, task.taskId, visible = false diff --git a/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/transition/ShellTransitionTests.java b/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/transition/ShellTransitionTests.java index 409b87723e79..81e6d071045a 100644 --- a/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/transition/ShellTransitionTests.java +++ b/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/transition/ShellTransitionTests.java @@ -442,6 +442,27 @@ public class ShellTransitionTests extends ShellTestCase { } @Test + public void testTransitionFilterAnimOverride() { + TransitionFilter filter = new TransitionFilter(); + filter.mRequirements = + new TransitionFilter.Requirement[]{new TransitionFilter.Requirement()}; + filter.mRequirements[0].mCustomAnimation = true; + filter.mRequirements[0].mModes = new int[]{TRANSIT_OPEN, TRANSIT_TO_FRONT}; + + final RunningTaskInfo taskInf = createTaskInfo(1); + final TransitionInfo openTask = new TransitionInfoBuilder(TRANSIT_OPEN) + .addChange(TRANSIT_OPEN, taskInf).build(); + assertFalse(filter.matches(openTask)); + + final TransitionInfo.AnimationOptions overOpts = + TransitionInfo.AnimationOptions.makeCustomAnimOptions("pakname", 0, 0, 0, true); + final TransitionInfo openTaskOpts = new TransitionInfoBuilder(TRANSIT_OPEN) + .addChange(TRANSIT_OPEN, taskInf).build(); + openTaskOpts.getChanges().get(0).setAnimationOptions(overOpts); + assertTrue(filter.matches(openTaskOpts)); + } + + @Test public void testRegisteredRemoteTransition() { Transitions transitions = createTestTransitions(); transitions.replaceDefaultHandlerForTest(mDefaultHandler); diff --git a/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/windowdecor/DesktopModeWindowDecorViewModelTests.kt b/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/windowdecor/DesktopModeWindowDecorViewModelTests.kt index 01c4f3ad6870..e26416047c56 100644 --- a/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/windowdecor/DesktopModeWindowDecorViewModelTests.kt +++ b/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/windowdecor/DesktopModeWindowDecorViewModelTests.kt @@ -103,6 +103,8 @@ import org.mockito.kotlin.whenever import org.mockito.quality.Strictness import java.util.Optional import java.util.function.Supplier +import junit.framework.Assert.assertFalse +import junit.framework.Assert.assertTrue /** * Tests of [DesktopModeWindowDecorViewModel] @@ -206,25 +208,13 @@ class DesktopModeWindowDecorViewModelTests : ShellTestCase() { val decoration = setUpMockDecorationForTask(task) onTaskOpening(task, taskSurface) + assertTrue(windowDecorByTaskIdSpy.contains(task.taskId)) task.setWindowingMode(WINDOWING_MODE_UNDEFINED) task.setActivityType(ACTIVITY_TYPE_UNDEFINED) onTaskChanging(task, taskSurface) - verify(mockDesktopModeWindowDecorFactory).create( - mContext, - mockDisplayController, - mockSplitScreenController, - mockTaskOrganizer, - task, - taskSurface, - mockMainHandler, - bgExecutor, - mockMainChoreographer, - mockSyncQueue, - mockRootTaskDisplayAreaOrganizer, - mockGenericLinksParser - ) + assertFalse(windowDecorByTaskIdSpy.contains(task.taskId)) verify(decoration).close() } @@ -238,38 +228,12 @@ class DesktopModeWindowDecorViewModelTests : ShellTestCase() { setUpMockDecorationForTask(task) onTaskChanging(task, taskSurface) - verify(mockDesktopModeWindowDecorFactory, never()).create( - mContext, - mockDisplayController, - mockSplitScreenController, - mockTaskOrganizer, - task, - taskSurface, - mockMainHandler, - bgExecutor, - mockMainChoreographer, - mockSyncQueue, - mockRootTaskDisplayAreaOrganizer, - mockGenericLinksParser - ) + assertFalse(windowDecorByTaskIdSpy.contains(task.taskId)) task.setWindowingMode(WINDOWING_MODE_FREEFORM) task.setActivityType(ACTIVITY_TYPE_STANDARD) onTaskChanging(task, taskSurface) - verify(mockDesktopModeWindowDecorFactory, times(1)).create( - mContext, - mockDisplayController, - mockSplitScreenController, - mockTaskOrganizer, - task, - taskSurface, - mockMainHandler, - bgExecutor, - mockMainChoreographer, - mockSyncQueue, - mockRootTaskDisplayAreaOrganizer, - mockGenericLinksParser - ) + assertTrue(windowDecorByTaskIdSpy.contains(task.taskId)) } @Test @@ -364,9 +328,7 @@ class DesktopModeWindowDecorViewModelTests : ShellTestCase() { task.setWindowingMode(ACTIVITY_TYPE_UNDEFINED) onTaskChanging(task) - verify(mockDesktopModeWindowDecorFactory, never()) - .create(any(), any(), any(), any(), eq(task), any(), any(), any(), any(), any(), - any(), any()) + assertFalse(windowDecorByTaskIdSpy.contains(task.taskId)) } @Test @@ -386,9 +348,7 @@ class DesktopModeWindowDecorViewModelTests : ShellTestCase() { setUpMockDecorationsForTasks(task) onTaskOpening(task) - verify(mockDesktopModeWindowDecorFactory) - .create(any(), any(), any(), any(), eq(task), any(), any(), any(), any(), - any(), any(), any()) + assertTrue(windowDecorByTaskIdSpy.contains(task.taskId)) } finally { mockitoSession.finishMocking() } @@ -404,9 +364,7 @@ class DesktopModeWindowDecorViewModelTests : ShellTestCase() { } onTaskOpening(task) - verify(mockDesktopModeWindowDecorFactory, never()) - .create(any(), any(), any(), any(), eq(task), any(), any(), any(), any(), any(), - any(), any()) + assertFalse(windowDecorByTaskIdSpy.contains(task.taskId)) } @Test @@ -422,9 +380,7 @@ class DesktopModeWindowDecorViewModelTests : ShellTestCase() { onTaskOpening(task) - verify(mockDesktopModeWindowDecorFactory, never()) - .create(any(), any(), any(), any(), eq(task), any(), any(), any(), any(), any(), - any(), any()) + assertFalse(windowDecorByTaskIdSpy.contains(task.taskId)) } @Test @@ -520,9 +476,7 @@ class DesktopModeWindowDecorViewModelTests : ShellTestCase() { doReturn(false).`when` { DesktopModeStatus.isDesktopModeSupported(any()) } onTaskOpening(task) - verify(mockDesktopModeWindowDecorFactory, never()) - .create(any(), any(), any(), any(), eq(task), any(), any(), any(), any(), any(), - any(), any()) + assertFalse(windowDecorByTaskIdSpy.contains(task.taskId)) } finally { mockitoSession.finishMocking() } @@ -545,9 +499,7 @@ class DesktopModeWindowDecorViewModelTests : ShellTestCase() { setUpMockDecorationsForTasks(task) onTaskOpening(task) - verify(mockDesktopModeWindowDecorFactory) - .create(any(), any(), any(), any(), eq(task), any(), any(), any(), any(), any(), - any(), any()) + assertTrue(windowDecorByTaskIdSpy.contains(task.taskId)) } finally { mockitoSession.finishMocking() } @@ -569,9 +521,7 @@ class DesktopModeWindowDecorViewModelTests : ShellTestCase() { setUpMockDecorationsForTasks(task) onTaskOpening(task) - verify(mockDesktopModeWindowDecorFactory) - .create(any(), any(), any(), any(), eq(task), any(), any(), any(), any(), any(), - any(), any()) + assertTrue(windowDecorByTaskIdSpy.contains(task.taskId)) } finally { mockitoSession.finishMocking() } @@ -693,7 +643,7 @@ class DesktopModeWindowDecorViewModelTests : ShellTestCase() { @WindowConfiguration.WindowingMode windowingMode: Int, activityType: Int = ACTIVITY_TYPE_STANDARD, focused: Boolean = true, - activityInfo: ActivityInfo = ActivityInfo() + activityInfo: ActivityInfo = ActivityInfo(), ): RunningTaskInfo { return TestRunningTaskInfoBuilder() .setDisplayId(displayId) @@ -709,8 +659,8 @@ class DesktopModeWindowDecorViewModelTests : ShellTestCase() { private fun setUpMockDecorationForTask(task: RunningTaskInfo): DesktopModeWindowDecoration { val decoration = mock(DesktopModeWindowDecoration::class.java) whenever( - mockDesktopModeWindowDecorFactory.create(any(), any(), any(), any(), eq(task), any(), - any(), any(), any(), any(), any(), any()) + mockDesktopModeWindowDecorFactory.create(any(), any(), any(), any(), any(), eq(task), + any(), any(), any(), any(), any(), any(), any()) ).thenReturn(decoration) decoration.mTaskInfo = task whenever(decoration.isFocused).thenReturn(task.isFocused) diff --git a/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/windowdecor/DesktopModeWindowDecorationTests.java b/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/windowdecor/DesktopModeWindowDecorationTests.java index cee9307379ea..04b1eed02950 100644 --- a/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/windowdecor/DesktopModeWindowDecorationTests.java +++ b/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/windowdecor/DesktopModeWindowDecorationTests.java @@ -826,10 +826,10 @@ public class DesktopModeWindowDecorationTests extends ShellTestCase { ActivityManager.RunningTaskInfo taskInfo, MaximizeMenuFactory maximizeMenuFactory) { final DesktopModeWindowDecoration windowDecor = new DesktopModeWindowDecoration(mContext, - mMockDisplayController, mMockSplitScreenController, mMockShellTaskOrganizer, - taskInfo, mMockSurfaceControl, mMockHandler, mBgExecutor, mMockChoreographer, - mMockSyncQueue, mMockRootTaskDisplayAreaOrganizer, mMockGenericLinksParser, - SurfaceControl.Builder::new, mMockTransactionSupplier, + mContext, mMockDisplayController, mMockSplitScreenController, + mMockShellTaskOrganizer, taskInfo, mMockSurfaceControl, mMockHandler, mBgExecutor, + mMockChoreographer, mMockSyncQueue, mMockRootTaskDisplayAreaOrganizer, + mMockGenericLinksParser, SurfaceControl.Builder::new, mMockTransactionSupplier, WindowContainerTransaction::new, SurfaceControl::new, mMockSurfaceControlViewHostFactory, maximizeMenuFactory, mMockHandleMenuFactory); windowDecor.setCaptionListeners(mMockTouchEventListener, mMockTouchEventListener, diff --git a/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/windowdecor/WindowDecorationTests.java b/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/windowdecor/WindowDecorationTests.java index ca6e03c45e7e..e6e2d0928240 100644 --- a/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/windowdecor/WindowDecorationTests.java +++ b/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/windowdecor/WindowDecorationTests.java @@ -51,6 +51,7 @@ import static org.mockito.Mockito.verify; import static org.mockito.Mockito.when; import static org.mockito.quality.Strictness.LENIENT; +import android.annotation.NonNull; import android.app.ActivityManager; import android.content.Context; import android.content.res.Resources; @@ -893,8 +894,8 @@ public class WindowDecorationTests extends ShellTestCase { } private TestWindowDecoration createWindowDecoration(ActivityManager.RunningTaskInfo taskInfo) { - return new TestWindowDecoration(mContext, mMockDisplayController, mMockShellTaskOrganizer, - taskInfo, mMockTaskSurface, + return new TestWindowDecoration(mContext, mContext, mMockDisplayController, + mMockShellTaskOrganizer, taskInfo, mMockTaskSurface, new MockObjectSupplier<>(mMockSurfaceControlBuilders, () -> createMockSurfaceControlBuilder(mock(SurfaceControl.class))), new MockObjectSupplier<>(mMockSurfaceControlTransactions, @@ -932,7 +933,8 @@ public class WindowDecorationTests extends ShellTestCase { } private class TestWindowDecoration extends WindowDecoration<TestView> { - TestWindowDecoration(Context context, DisplayController displayController, + TestWindowDecoration(Context context, @NonNull Context userContext, + DisplayController displayController, ShellTaskOrganizer taskOrganizer, ActivityManager.RunningTaskInfo taskInfo, SurfaceControl taskSurface, Supplier<SurfaceControl.Builder> surfaceControlBuilderSupplier, @@ -940,7 +942,7 @@ public class WindowDecorationTests extends ShellTestCase { Supplier<WindowContainerTransaction> windowContainerTransactionSupplier, Supplier<SurfaceControl> surfaceControlSupplier, SurfaceControlViewHostFactory surfaceControlViewHostFactory) { - super(context, displayController, taskOrganizer, taskInfo, taskSurface, + super(context, userContext, displayController, taskOrganizer, taskInfo, taskSurface, surfaceControlBuilderSupplier, surfaceControlTransactionSupplier, windowContainerTransactionSupplier, surfaceControlSupplier, surfaceControlViewHostFactory); diff --git a/libs/hwui/Android.bp b/libs/hwui/Android.bp index e302fa8b1fc3..d71f3b6884ae 100644 --- a/libs/hwui/Android.bp +++ b/libs/hwui/Android.bp @@ -736,6 +736,7 @@ cc_defaults { cc_test { name: "hwui_unit_tests", + test_config: "tests/unit/AndroidTest.xml", defaults: [ "hwui_test_defaults", "android_graphics_apex", @@ -803,6 +804,7 @@ cc_test { cc_benchmark { name: "hwuimacro", + test_config: "tests/macrobench/AndroidTest.xml", defaults: ["hwui_test_defaults"], static_libs: ["libhwui"], @@ -822,6 +824,7 @@ cc_benchmark { cc_benchmark { name: "hwuimicro", + test_config: "tests/microbench/AndroidTest.xml", defaults: ["hwui_test_defaults"], static_libs: ["libhwui_static"], diff --git a/libs/hwui/Properties.cpp b/libs/hwui/Properties.cpp index 5d3bc89b40dd..d184f64b1c2c 100644 --- a/libs/hwui/Properties.cpp +++ b/libs/hwui/Properties.cpp @@ -101,6 +101,8 @@ float Properties::maxHdrHeadroomOn8bit = 5.f; // TODO: Refine this number bool Properties::clipSurfaceViews = false; bool Properties::hdr10bitPlus = false; +int Properties::timeoutMultiplier = 1; + StretchEffectBehavior Properties::stretchEffectBehavior = StretchEffectBehavior::ShaderHWUI; DrawingEnabled Properties::drawingEnabled = DrawingEnabled::NotInitialized; @@ -174,6 +176,8 @@ bool Properties::load() { base::GetBoolProperty("debug.hwui.clip_surfaceviews", hwui_flags::clip_surfaceviews()); hdr10bitPlus = hwui_flags::hdr_10bit_plus(); + timeoutMultiplier = android::base::GetIntProperty("ro.hw_timeout_multiplier", 1); + return (prevDebugLayersUpdates != debugLayersUpdates) || (prevDebugOverdraw != debugOverdraw); } diff --git a/libs/hwui/Properties.h b/libs/hwui/Properties.h index d3176f6879d2..e2646422030e 100644 --- a/libs/hwui/Properties.h +++ b/libs/hwui/Properties.h @@ -343,6 +343,8 @@ public: static bool clipSurfaceViews; static bool hdr10bitPlus; + static int timeoutMultiplier; + static StretchEffectBehavior getStretchEffectBehavior() { return stretchEffectBehavior; } diff --git a/libs/hwui/Readback.cpp b/libs/hwui/Readback.cpp index afe4c3896ed2..2f15722a23e0 100644 --- a/libs/hwui/Readback.cpp +++ b/libs/hwui/Readback.cpp @@ -91,8 +91,10 @@ void Readback::copySurfaceInto(ANativeWindow* window, const std::shared_ptr<Copy { ATRACE_NAME("sync_wait"); - if (sourceFence != -1 && sync_wait(sourceFence.get(), 500 /* ms */) != NO_ERROR) { - ALOGE("Timeout (500ms) exceeded waiting for buffer fence, abandoning readback attempt"); + int syncWaitTimeoutMs = 500 * Properties::timeoutMultiplier; + if (sourceFence != -1 && sync_wait(sourceFence.get(), syncWaitTimeoutMs) != NO_ERROR) { + ALOGE("Timeout (%dms) exceeded waiting for buffer fence, abandoning readback attempt", + syncWaitTimeoutMs); return request->onCopyFinished(CopyResult::Timeout); } } @@ -109,9 +111,8 @@ void Readback::copySurfaceInto(ANativeWindow* window, const std::shared_ptr<Copy sk_sp<SkColorSpace> colorSpace = DataSpaceToColorSpace(static_cast<android_dataspace>(dataspace)); - sk_sp<SkImage> image = - SkImages::DeferredFromAHardwareBuffer(sourceBuffer.get(), kPremul_SkAlphaType, - colorSpace); + sk_sp<SkImage> image = SkImages::DeferredFromAHardwareBuffer(sourceBuffer.get(), + kPremul_SkAlphaType, colorSpace); if (!image.get()) { return request->onCopyFinished(CopyResult::UnknownError); diff --git a/libs/hwui/tests/macrobench/AndroidTest.xml b/libs/hwui/tests/macrobench/AndroidTest.xml new file mode 100644 index 000000000000..5b8576d444cd --- /dev/null +++ b/libs/hwui/tests/macrobench/AndroidTest.xml @@ -0,0 +1,28 @@ +<?xml version="1.0" encoding="utf-8"?> +<!-- Copyright 2024 The Android Open Source Project + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. +--> +<configuration description="Config for hwuimacro"> + <target_preparer class="com.android.tradefed.targetprep.PushFilePreparer"> + <option name="cleanup" value="true" /> + <option name="push" value="hwuimacro->/data/local/tmp/benchmarktest/hwuimacro" /> + </target_preparer> + <option name="test-suite-tag" value="apct" /> + <option name="not-shardable" value="true" /> + <test class="com.android.tradefed.testtype.GoogleBenchmarkTest" > + <option name="native-benchmark-device-path" value="/data/local/tmp/benchmarktest" /> + <option name="benchmark-module-name" value="hwuimacro" /> + <option name="file-exclusion-filter-regex" value=".*\.config$" /> + </test> +</configuration> diff --git a/libs/hwui/tests/macrobench/how_to_run.txt b/libs/hwui/tests/macrobench/how_to_run.txt index 3c3d36a8977f..59ef25a3aacc 100644 --- a/libs/hwui/tests/macrobench/how_to_run.txt +++ b/libs/hwui/tests/macrobench/how_to_run.txt @@ -3,3 +3,7 @@ adb push $OUT/data/benchmarktest/hwuimacro/hwuimacro /data/benchmarktest/hwuimac adb shell /data/benchmarktest/hwuimacro/hwuimacro shadowgrid2 --onscreen Pass --help to get help + +OR (if you don't need to pass arguments) + +atest hwuimacro diff --git a/libs/hwui/AndroidTest.xml b/libs/hwui/tests/microbench/AndroidTest.xml index 75f61f5f7f9d..d67305dfa323 100644 --- a/libs/hwui/AndroidTest.xml +++ b/libs/hwui/tests/microbench/AndroidTest.xml @@ -1,5 +1,5 @@ <?xml version="1.0" encoding="utf-8"?> -<!-- Copyright (C) 2017 The Android Open Source Project +<!-- Copyright 2024 The Android Open Source Project Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. @@ -16,24 +16,13 @@ <configuration description="Config for hwuimicro"> <target_preparer class="com.android.tradefed.targetprep.PushFilePreparer"> <option name="cleanup" value="true" /> - <option name="push" value="hwui_unit_tests->/data/local/tmp/nativetest/hwui_unit_tests" /> <option name="push" value="hwuimicro->/data/local/tmp/benchmarktest/hwuimicro" /> - <option name="push" value="hwuimacro->/data/local/tmp/benchmarktest/hwuimacro" /> </target_preparer> <option name="test-suite-tag" value="apct" /> <option name="not-shardable" value="true" /> - <test class="com.android.tradefed.testtype.GTest" > - <option name="native-test-device-path" value="/data/local/tmp/nativetest" /> - <option name="module-name" value="hwui_unit_tests" /> - </test> <test class="com.android.tradefed.testtype.GoogleBenchmarkTest" > <option name="native-benchmark-device-path" value="/data/local/tmp/benchmarktest" /> <option name="benchmark-module-name" value="hwuimicro" /> <option name="file-exclusion-filter-regex" value=".*\.config$" /> </test> - <test class="com.android.tradefed.testtype.GoogleBenchmarkTest" > - <option name="native-benchmark-device-path" value="/data/local/tmp/benchmarktest" /> - <option name="benchmark-module-name" value="hwuimacro" /> - <option name="file-exclusion-filter-regex" value=".*\.config$" /> - </test> </configuration> diff --git a/libs/hwui/tests/microbench/how_to_run.txt b/libs/hwui/tests/microbench/how_to_run.txt index 915fe5d959f9..c7ddc1a70cd7 100755 --- a/libs/hwui/tests/microbench/how_to_run.txt +++ b/libs/hwui/tests/microbench/how_to_run.txt @@ -1,3 +1,7 @@ mmm -j8 frameworks/base/libs/hwui && adb push $OUT/data/benchmarktest/hwuimicro/hwuimicro /data/benchmarktest/hwuimicro/hwuimicro && adb shell /data/benchmarktest/hwuimicro/hwuimicro + +OR + +atest hwuimicro diff --git a/libs/hwui/tests/unit/AndroidTest.xml b/libs/hwui/tests/unit/AndroidTest.xml new file mode 100644 index 000000000000..dc586c9b740c --- /dev/null +++ b/libs/hwui/tests/unit/AndroidTest.xml @@ -0,0 +1,27 @@ +<?xml version="1.0" encoding="utf-8"?> +<!-- Copyright 2024 The Android Open Source Project + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. +--> +<configuration description="Config for hwui_unit_tests"> + <target_preparer class="com.android.tradefed.targetprep.PushFilePreparer"> + <option name="cleanup" value="true" /> + <option name="push" value="hwui_unit_tests->/data/local/tmp/nativetest/hwui_unit_tests" /> + </target_preparer> + <option name="test-suite-tag" value="apct" /> + <option name="not-shardable" value="true" /> + <test class="com.android.tradefed.testtype.GTest" > + <option name="native-test-device-path" value="/data/local/tmp/nativetest" /> + <option name="module-name" value="hwui_unit_tests" /> + </test> +</configuration> diff --git a/libs/hwui/tests/unit/how_to_run.txt b/libs/hwui/tests/unit/how_to_run.txt index c11d6eb33358..1a35adf6b11b 100755 --- a/libs/hwui/tests/unit/how_to_run.txt +++ b/libs/hwui/tests/unit/how_to_run.txt @@ -2,3 +2,11 @@ mmm -j8 frameworks/base/libs/hwui && adb push $ANDROID_PRODUCT_OUT/data/nativetest/hwui_unit_tests/hwui_unit_tests \ /data/nativetest/hwui_unit_tests/hwui_unit_tests && adb shell /data/nativetest/hwui_unit_tests/hwui_unit_tests + +OR + +atest hwui_unit_tests + +OR, if you need arguments, they can be passed as native-test-flags, as in: + +atest hwui_unit_tests -- --test-arg com.android.tradefed.testtype.GTest:native-test-flag:"--renderer=skiavk" diff --git a/libs/hwui/tests/unit/main.cpp b/libs/hwui/tests/unit/main.cpp index 76cbc8abc808..3fd15c4c9c51 100644 --- a/libs/hwui/tests/unit/main.cpp +++ b/libs/hwui/tests/unit/main.cpp @@ -15,6 +15,7 @@ */ #include <getopt.h> +#include <log/log.h> #include <signal.h> #include "Properties.h" @@ -65,6 +66,19 @@ static RenderPipelineType parseRenderer(const char* renderer) { return RenderPipelineType::SkiaGL; } +static constexpr const char* renderPipelineTypeName(const RenderPipelineType renderPipelineType) { + switch (renderPipelineType) { + case RenderPipelineType::SkiaGL: + return "SkiaGL"; + case RenderPipelineType::SkiaVulkan: + return "SkiaVulkan"; + case RenderPipelineType::SkiaCpu: + return "SkiaCpu"; + case RenderPipelineType::NotInitialized: + return "NotInitialized"; + } +} + struct Options { RenderPipelineType renderer = RenderPipelineType::SkiaGL; }; @@ -118,6 +132,7 @@ int main(int argc, char* argv[]) { auto opts = parseOptions(argc, argv); Properties::overrideRenderPipelineType(opts.renderer); + ALOGI("Starting HWUI unit tests with %s pipeline", renderPipelineTypeName(opts.renderer)); // Run the tests testing::InitGoogleTest(&argc, argv); diff --git a/location/java/com/android/internal/location/GpsNetInitiatedHandler.java b/location/java/com/android/internal/location/GpsNetInitiatedHandler.java index 0d5af50d08b5..8b6194fa66f5 100644 --- a/location/java/com/android/internal/location/GpsNetInitiatedHandler.java +++ b/location/java/com/android/internal/location/GpsNetInitiatedHandler.java @@ -27,6 +27,7 @@ import android.telephony.TelephonyManager; import android.telephony.emergency.EmergencyNumber; import android.util.Log; +import com.android.internal.annotations.KeepForWeakReference; import com.android.internal.telephony.flags.Flags; import java.util.concurrent.TimeUnit; @@ -94,6 +95,7 @@ public class GpsNetInitiatedHandler { // The internal implementation of TelephonyManager uses WeakReference so we have to keep a // reference here. + @KeepForWeakReference private final EmergencyCallListener mEmergencyCallListener = new EmergencyCallListener(); private final EmergencyCallCallback mEmergencyCallCallback; diff --git a/media/java/android/media/AudioAttributes.java b/media/java/android/media/AudioAttributes.java index 42175628a45d..1024a5519965 100644 --- a/media/java/android/media/AudioAttributes.java +++ b/media/java/android/media/AudioAttributes.java @@ -578,6 +578,8 @@ public final class AudioAttributes implements Parcelable { }); private AudioAttributes() { + mBundle = null; + mFormattedTags = ""; } /** diff --git a/nfc/java/android/nfc/NfcAdapter.java b/nfc/java/android/nfc/NfcAdapter.java index 395f81d73351..0ffab4ba3eaf 100644 --- a/nfc/java/android/nfc/NfcAdapter.java +++ b/nfc/java/android/nfc/NfcAdapter.java @@ -1166,10 +1166,11 @@ public final class NfcAdapter { /** - * Returns whether the device supports observer mode or not. When observe - * mode is enabled, the NFC hardware will listen for NFC readers, but not - * respond to them. When observe mode is disabled, the NFC hardware will - * resoond to the reader and proceed with the transaction. + * Returns whether the device supports observe mode or not. When observe mode is enabled, the + * NFC hardware will listen to NFC readers, but not respond to them. While enabled, observed + * polling frames will be sent to the APDU service (see {@link #setObserveModeEnabled(boolean)}. + * When observe mode is disabled (or if it's not supported), the NFC hardware will automatically + * respond to the reader and proceed with the transaction. * @return true if the mode is supported, false otherwise. */ @FlaggedApi(Flags.FLAG_NFC_OBSERVE_MODE) @@ -1193,9 +1194,10 @@ public final class NfcAdapter { * and simply observe and notify the APDU service of polling loop frames. See * {@link #isObserveModeSupported()} for a description of observe mode. Only the package of the * currently preferred service (the service set as preferred by the current foreground - * application via {@link CardEmulation#setPreferredService(Activity, ComponentName)} or the - * current Default Wallet Role Holder {@link android.app.role.RoleManager#ROLE_WALLET}), - * otherwise a call to this method will fail and return false. + * application via {@link android.nfc.cardemulation.CardEmulation#setPreferredService(Activity, + * android.content.ComponentName)} or the current Default Wallet Role Holder + * {@link android.app.role.RoleManager#ROLE_WALLET}), otherwise a call to this method will fail + * and return false. * * @param enabled false disables observe mode to allow the transaction to proceed while true * enables observe mode and does not allow transactions to proceed. diff --git a/packages/InputDevices/res/raw/keyboard_layout_arabic.kcm b/packages/InputDevices/res/raw/keyboard_layout_arabic.kcm index 9c2064c9b8ea..8c6880b111a5 100644 --- a/packages/InputDevices/res/raw/keyboard_layout_arabic.kcm +++ b/packages/InputDevices/res/raw/keyboard_layout_arabic.kcm @@ -58,7 +58,8 @@ key 5 { label: '5' base: '\u0665' capslock: '5' - shift: '%' + shift: '\u066a' + shift+capslock: '%' } key 6 { diff --git a/packages/PackageInstaller/res/values-ar/strings.xml b/packages/PackageInstaller/res/values-ar/strings.xml index de91c09c007f..a82f982b203e 100644 --- a/packages/PackageInstaller/res/values-ar/strings.xml +++ b/packages/PackageInstaller/res/values-ar/strings.xml @@ -66,9 +66,9 @@ <string name="archive_application_text_current_user_private_profile" msgid="1958423158655599132">"هل تريد أرشفة هذا التطبيق المحفوظ في المساحة الخاصّة؟ سيتم حفظ بياناتك الشخصية."</string> <string name="uninstall_application_text_all_users" msgid="575491774380227119">"هل تريد إزالة هذا التطبيق "<b>"لكل"</b>" المستخدمين؟ ستتم إزالة التطبيق وبياناته من "<b>"كل"</b>" المستخدمين على هذا الجهاز."</string> <string name="uninstall_application_text_user" msgid="498072714173920526">"هل تريد إزالة هذا التطبيق للمستخدم <xliff:g id="USERNAME">%1$s</xliff:g>؟"</string> - <string name="uninstall_application_text_current_user_work_profile" msgid="8788387739022366193">"هل تريد إزالة تثبيت هذا التطبيق من ملفك الشخصي للعمل؟"</string> + <string name="uninstall_application_text_current_user_work_profile" msgid="8788387739022366193">"هل تريد إزالة تثبيت هذا التطبيق من ملف العمل الخاص بك؟"</string> <string name="uninstall_update_text" msgid="863648314632448705">"هل تريد استبدال هذا التطبيق بإصدار المصنع؟ ستتم إزالة جميع البيانات."</string> - <string name="uninstall_update_text_multiuser" msgid="8992883151333057227">"هل تريد إعادة ضبط هذا التطبيق على الإعدادات الأصلية؟ سؤدي ذلك إلى إزالة جميع البيانات، كما سيؤثر على جميع مستخدمي هذا الجهاز، بما في ذلك من لديهم ملفات شخصية للعمل."</string> + <string name="uninstall_update_text_multiuser" msgid="8992883151333057227">"هل تريد إعادة ضبط هذا التطبيق على الإعدادات الأصلية؟ سؤدي ذلك إلى إزالة جميع البيانات، كما سيؤثر على جميع مستخدمي هذا الجهاز، بما في ذلك من لديهم ملفات للعمل."</string> <string name="uninstall_keep_data" msgid="7002379587465487550">"الاحتفاظ بـ <xliff:g id="SIZE">%1$s</xliff:g> من بيانات التطبيق."</string> <string name="uninstall_application_text_current_user_clone_profile" msgid="835170400160011636">"هل تريد حذف هذا التطبيق؟"</string> <string name="uninstall_application_text_with_clone_instance" msgid="6944473334273349036">"هل تريد إلغاء تثبيت هذا التطبيق؟ سيتم أيضًا حذف نسخة \"<xliff:g id="PACKAGE_LABEL">%1$s</xliff:g>\" الطبق الأصل."</string> diff --git a/packages/SettingsLib/DataStore/src/com/android/settingslib/datastore/BackupRestoreStorageManager.kt b/packages/SettingsLib/DataStore/src/com/android/settingslib/datastore/BackupRestoreStorageManager.kt index b4a91726ac1d..ce02404b0f06 100644 --- a/packages/SettingsLib/DataStore/src/com/android/settingslib/datastore/BackupRestoreStorageManager.kt +++ b/packages/SettingsLib/DataStore/src/com/android/settingslib/datastore/BackupRestoreStorageManager.kt @@ -129,7 +129,7 @@ class BackupRestoreStorageManager private constructor(private val application: A } } - override fun onChanged(reason: Int) = onKeyChanged(null, reason) + override fun onChanged(observable: Observable, reason: Int) = onKeyChanged(null, reason) override fun onKeyChanged(key: Any?, reason: Int) { notifyBackupManager(key, reason) diff --git a/packages/SettingsLib/DataStore/src/com/android/settingslib/datastore/KeyedObserver.kt b/packages/SettingsLib/DataStore/src/com/android/settingslib/datastore/KeyedObserver.kt index ede7c63d00b4..4ce1d3790e8b 100644 --- a/packages/SettingsLib/DataStore/src/com/android/settingslib/datastore/KeyedObserver.kt +++ b/packages/SettingsLib/DataStore/src/com/android/settingslib/datastore/KeyedObserver.kt @@ -103,7 +103,7 @@ interface KeyedObservable<K> { } /** A thread safe implementation of [KeyedObservable]. */ -class KeyedDataObservable<K> : KeyedObservable<K> { +open class KeyedDataObservable<K> : KeyedObservable<K> { // Instead of @GuardedBy("this"), guarded by itself because KeyedDataObservable object could be // synchronized outside by the holder @GuardedBy("itself") private val observers = WeakHashMap<KeyedObserver<K?>, Executor>() diff --git a/packages/SettingsLib/DataStore/src/com/android/settingslib/datastore/ObservableBackupRestoreStorage.kt b/packages/SettingsLib/DataStore/src/com/android/settingslib/datastore/ObservableBackupRestoreStorage.kt index 0e399c01e763..300d240351da 100644 --- a/packages/SettingsLib/DataStore/src/com/android/settingslib/datastore/ObservableBackupRestoreStorage.kt +++ b/packages/SettingsLib/DataStore/src/com/android/settingslib/datastore/ObservableBackupRestoreStorage.kt @@ -21,5 +21,7 @@ package com.android.settingslib.datastore * * This class provides the [Observable] implementations on top of [DataObservable] by delegation. */ -abstract class ObservableBackupRestoreStorage : - BackupRestoreStorage(), Observable by DataObservable() +abstract class ObservableBackupRestoreStorage : BackupRestoreStorage(), ObservableDelegation { + + final override val observableDelegate: Observable = DataObservable(this) +} diff --git a/packages/SettingsLib/DataStore/src/com/android/settingslib/datastore/Observer.kt b/packages/SettingsLib/DataStore/src/com/android/settingslib/datastore/Observer.kt index 98d0f6e3f9a1..6af3d1cde388 100644 --- a/packages/SettingsLib/DataStore/src/com/android/settingslib/datastore/Observer.kt +++ b/packages/SettingsLib/DataStore/src/com/android/settingslib/datastore/Observer.kt @@ -32,10 +32,11 @@ fun interface Observer { * * This callback will run in the given [Executor] when observer is added. * + * @param observable observable of the change * @param reason the reason of change * @see [Observable.addObserver] for the notices. */ - fun onChanged(reason: Int) + fun onChanged(observable: Observable, reason: Int) } /** An observable object allows to observe change with [Observer]. */ @@ -68,8 +69,21 @@ interface Observable { fun notifyChange(reason: Int) } +/** Delegation of [Observable]. */ +interface ObservableDelegation : Observable { + /** [Observable] to delegate. */ + val observableDelegate: Observable + + override fun addObserver(observer: Observer, executor: Executor) = + observableDelegate.addObserver(observer, executor) + + override fun removeObserver(observer: Observer) = observableDelegate.removeObserver(observer) + + override fun notifyChange(reason: Int) = observableDelegate.notifyChange(reason) +} + /** A thread safe implementation of [Observable]. */ -class DataObservable : Observable { +class DataObservable(private val observable: Observable) : Observable { // Instead of @GuardedBy("this"), guarded by itself because DataObservable object could be // synchronized outside by the holder @GuardedBy("itself") private val observers = WeakHashMap<Observer, Executor>() @@ -90,7 +104,7 @@ class DataObservable : Observable { val entries = synchronized(observers) { observers.entries.toTypedArray() } for (entry in entries) { val observer = entry.key // avoid reference "entry" - entry.value.execute { observer.onChanged(reason) } + entry.value.execute { observer.onChanged(observable, reason) } } } } diff --git a/packages/SettingsLib/DataStore/src/com/android/settingslib/datastore/SharedPreferencesObservable.kt b/packages/SettingsLib/DataStore/src/com/android/settingslib/datastore/SharedPreferencesObservable.kt new file mode 100644 index 000000000000..e70ec5b2e38e --- /dev/null +++ b/packages/SettingsLib/DataStore/src/com/android/settingslib/datastore/SharedPreferencesObservable.kt @@ -0,0 +1,45 @@ +/* + * Copyright (C) 2024 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.android.settingslib.datastore + +import android.content.SharedPreferences + +/** [SharedPreferences] based [KeyedDataObservable]. */ +class SharedPreferencesObservable(private val sharedPreferences: SharedPreferences) : + KeyedDataObservable<String>(), AutoCloseable { + + private val listener = createSharedPreferenceListener() + + init { + sharedPreferences.registerOnSharedPreferenceChangeListener(listener) + } + + override fun close() { + sharedPreferences.unregisterOnSharedPreferenceChangeListener(listener) + } +} + +/** Creates [SharedPreferences.OnSharedPreferenceChangeListener] for [KeyedObservable]. */ +internal fun KeyedObservable<String>.createSharedPreferenceListener() = + SharedPreferences.OnSharedPreferenceChangeListener { _, key -> + if (key != null) { + notifyChange(key, DataChangeReason.UPDATE) + } else { + // On Android >= R, SharedPreferences.Editor.clear() will trigger this case + notifyChange(DataChangeReason.DELETE) + } + } diff --git a/packages/SettingsLib/DataStore/src/com/android/settingslib/datastore/SharedPreferencesStorage.kt b/packages/SettingsLib/DataStore/src/com/android/settingslib/datastore/SharedPreferencesStorage.kt index 20a95d7efc4b..0ca91cd4357a 100644 --- a/packages/SettingsLib/DataStore/src/com/android/settingslib/datastore/SharedPreferencesStorage.kt +++ b/packages/SettingsLib/DataStore/src/com/android/settingslib/datastore/SharedPreferencesStorage.kt @@ -80,15 +80,7 @@ constructor( return context.getSharedPreferences(intermediateName, Context.MODE_MULTI_PROCESS) } - private val sharedPreferencesListener = - SharedPreferences.OnSharedPreferenceChangeListener { _, key -> - if (key != null) { - notifyChange(key, DataChangeReason.UPDATE) - } else { - // On Android >= R, SharedPreferences.Editor.clear() will trigger this case - notifyChange(DataChangeReason.DELETE) - } - } + private val sharedPreferencesListener = createSharedPreferenceListener() init { // listener is weakly referenced, so unregister is optional @@ -191,8 +183,7 @@ constructor( else -> { Log.e( LOG_TAG, - "[$name] $operation $key=$value, unknown type: ${value?.javaClass}" - ) + "[$name] $operation $key=$value, unknown type: ${value?.javaClass}") } } } diff --git a/packages/SettingsLib/DataStore/tests/src/com/android/settingslib/datastore/BackupRestoreStorageManagerTest.kt b/packages/SettingsLib/DataStore/tests/src/com/android/settingslib/datastore/BackupRestoreStorageManagerTest.kt index 19c574a843ca..97b473c46911 100644 --- a/packages/SettingsLib/DataStore/tests/src/com/android/settingslib/datastore/BackupRestoreStorageManagerTest.kt +++ b/packages/SettingsLib/DataStore/tests/src/com/android/settingslib/datastore/BackupRestoreStorageManagerTest.kt @@ -159,7 +159,7 @@ class BackupRestoreStorageManagerTest { verify(keyedObserver).onKeyChanged("key", DataChangeReason.RESTORE) verify(anyKeyObserver).onKeyChanged(null, DataChangeReason.RESTORE) - verify(observer).onChanged(DataChangeReason.RESTORE) + verify(observer).onChanged(fileStorage, DataChangeReason.RESTORE) if (isRobolectric()) { Shadows.shadowOf(BackupManager(application)).apply { assertThat(isDataChanged).isFalse() @@ -187,7 +187,7 @@ class BackupRestoreStorageManagerTest { } fileStorage.notifyChange(DataChangeReason.UPDATE) - verify(observer).onChanged(DataChangeReason.UPDATE) + verify(observer).onChanged(fileStorage, DataChangeReason.UPDATE) verify(keyedObserver, never()).onKeyChanged(any(), any()) verify(anyKeyObserver, never()).onKeyChanged(any(), any()) reset(observer) @@ -197,7 +197,7 @@ class BackupRestoreStorageManagerTest { } keyedStorage.notifyChange("key", DataChangeReason.DELETE) - verify(observer, never()).onChanged(any()) + verify(observer, never()).onChanged(any(), any()) verify(keyedObserver).onKeyChanged("key", DataChangeReason.DELETE) verify(anyKeyObserver).onKeyChanged("key", DataChangeReason.DELETE) backupManager?.apply { @@ -209,7 +209,7 @@ class BackupRestoreStorageManagerTest { // backup manager is not notified for restore event fileStorage.notifyChange(DataChangeReason.RESTORE) keyedStorage.notifyChange("key", DataChangeReason.RESTORE) - verify(observer).onChanged(DataChangeReason.RESTORE) + verify(observer).onChanged(fileStorage, DataChangeReason.RESTORE) verify(keyedObserver).onKeyChanged("key", DataChangeReason.RESTORE) verify(anyKeyObserver).onKeyChanged("key", DataChangeReason.RESTORE) backupManager?.apply { @@ -225,7 +225,10 @@ class BackupRestoreStorageManagerTest { } private class FileStorage(override val name: String) : - BackupRestoreFileStorage(getApplicationContext(), "file"), Observable by DataObservable() + BackupRestoreFileStorage(getApplicationContext(), "file"), ObservableDelegation { + + override val observableDelegate: Observable = DataObservable(this) + } private class DummyBackupAgentHelper : BackupAgentHelper() { val backupHelpers = mutableMapOf<String, BackupHelper>() diff --git a/packages/SettingsLib/DataStore/tests/src/com/android/settingslib/datastore/ObserverTest.kt b/packages/SettingsLib/DataStore/tests/src/com/android/settingslib/datastore/ObserverTest.kt index 5d0303c06d41..bd114d1a569f 100644 --- a/packages/SettingsLib/DataStore/tests/src/com/android/settingslib/datastore/ObserverTest.kt +++ b/packages/SettingsLib/DataStore/tests/src/com/android/settingslib/datastore/ObserverTest.kt @@ -24,6 +24,7 @@ import java.util.concurrent.atomic.AtomicInteger import org.junit.Assert.assertThrows import org.junit.Test import org.junit.runner.RunWith +import org.mockito.kotlin.any import org.mockito.kotlin.mock import org.mockito.kotlin.never import org.mockito.kotlin.reset @@ -33,10 +34,11 @@ import org.mockito.kotlin.verify class ObserverTest { private val observer1 = mock<Observer>() private val observer2 = mock<Observer>() + private val originalObservable = mock<Observable>() private val executor1: Executor = MoreExecutors.directExecutor() private val executor2: Executor = MoreExecutors.newDirectExecutorService() - private val observable = DataObservable() + private val observable = DataObservable(originalObservable) @Test fun addObserver_sameExecutor() { @@ -55,7 +57,7 @@ class ObserverTest { @Test fun addObserver_weaklyReferenced() { val counter = AtomicInteger() - var observer: Observer? = Observer { counter.incrementAndGet() } + var observer: Observer? = Observer { _, _ -> counter.incrementAndGet() } observable.addObserver(observer!!, executor1) observable.notifyChange(DataChangeReason.UPDATE) @@ -77,21 +79,21 @@ class ObserverTest { observable.notifyChange(DataChangeReason.DELETE) - verify(observer1).onChanged(DataChangeReason.DELETE) - verify(observer2).onChanged(DataChangeReason.DELETE) + verify(observer1).onChanged(originalObservable, DataChangeReason.DELETE) + verify(observer2).onChanged(originalObservable, DataChangeReason.DELETE) reset(observer1, observer2) observable.removeObserver(observer2) observable.notifyChange(DataChangeReason.UPDATE) - verify(observer1).onChanged(DataChangeReason.UPDATE) - verify(observer2, never()).onChanged(DataChangeReason.UPDATE) + verify(observer1).onChanged(originalObservable, DataChangeReason.UPDATE) + verify(observer2, never()).onChanged(any(), any()) } @Test fun notifyChange_addObserverWithinCallback() { // ConcurrentModificationException is raised if it is not implemented correctly - val observer = Observer { observable.addObserver(observer1, executor1) } + val observer = Observer { _, _ -> observable.addObserver(observer1, executor1) } observable.addObserver(observer, executor1) observable.notifyChange(DataChangeReason.UPDATE) observable.removeObserver(observer) diff --git a/packages/SettingsLib/res/values-af/strings.xml b/packages/SettingsLib/res/values-af/strings.xml index 193d0bc6e4e3..e612229e1611 100644 --- a/packages/SettingsLib/res/values-af/strings.xml +++ b/packages/SettingsLib/res/values-af/strings.xml @@ -430,8 +430,7 @@ <string name="force_allow_on_external_summary" msgid="8525425782530728238">"Maak dat enige program na eksterne berging geskryf kan word, ongeag manifeswaardes"</string> <string name="force_resizable_activities" msgid="7143612144399959606">"Dwing aktiwiteite om verstelbaar te wees"</string> <string name="force_resizable_activities_summary" msgid="2490382056981583062">"Maak die groottes van alle aktiwiteite verstelbaar vir veelvuldige vensters, ongeag manifeswaardes."</string> - <string name="enable_freeform_support" msgid="8409932201445109106">"Aktiveer vryevormvensters (vorige)"</string> - <string name="enable_freeform_support_summary" msgid="2242481082356957934">"Aktiveer steun vir eksperimentele vorige vryevormvensters."</string> + <string name="enable_freeform_support" msgid="7599125687603914253">"Aktiveer vormvrye vensters"</string> <string name="local_backup_password_title" msgid="4631017948933578709">"Werkskerm-rugsteunwagwoord"</string> <string name="local_backup_password_summary_none" msgid="7646898032616361714">"Volle rekenaarrugsteune word nie tans beskerm nie"</string> <string name="local_backup_password_summary_change" msgid="1707357670383995567">"Tik om die wagwoord vir volledige rekenaarrugsteune te verander of te verwyder"</string> @@ -496,7 +495,8 @@ <string name="power_charging" msgid="6727132649743436802">"<xliff:g id="LEVEL">%1$s</xliff:g> – <xliff:g id="STATE">%2$s</xliff:g>"</string> <string name="power_remaining_charging_duration_only" msgid="8085099012811384899">"<xliff:g id="TIME">%1$s</xliff:g> oor tot vol"</string> <string name="power_charging_duration" msgid="6127154952524919719">"<xliff:g id="LEVEL">%1$s</xliff:g> – <xliff:g id="TIME">%2$s</xliff:g> oor tot vol"</string> - <string name="power_charging_limited" msgid="8202147604844938236">"<xliff:g id="LEVEL">%1$s</xliff:g> – Laaiproses word geoptimeer"</string> + <!-- no translation found for power_charging_limited (4144004473976005214) --> + <skip /> <string name="power_charging_future_paused" msgid="1809543660923642799">"<xliff:g id="LEVEL">%1$s</xliff:g> – Laai tans"</string> <string name="power_fast_charging_duration_v2" msgid="3797735998640359490">"<xliff:g id="LEVEL">%1$s</xliff:g> – <xliff:g id="STATUS">%2$s</xliff:g> – Volgelaai teen <xliff:g id="TIME">%3$s</xliff:g>"</string> <string name="power_charging_duration_v2" msgid="2938998284074003248">"<xliff:g id="LEVEL">%1$s</xliff:g> – Volgelaai teen <xliff:g id="TIME">%2$s</xliff:g>"</string> diff --git a/packages/SettingsLib/res/values-am/strings.xml b/packages/SettingsLib/res/values-am/strings.xml index 606a01ce9a2f..7556de6cdb37 100644 --- a/packages/SettingsLib/res/values-am/strings.xml +++ b/packages/SettingsLib/res/values-am/strings.xml @@ -430,8 +430,7 @@ <string name="force_allow_on_external_summary" msgid="8525425782530728238">"የዝርዝር ሰነዶች እሴቶች ግምት ውስጥ ሳያስገባ ማንኛውም መተግበሪያ ወደ ውጫዊ ማከማቻው ለመጻፍ ብቁ ያደርጋል"</string> <string name="force_resizable_activities" msgid="7143612144399959606">"እንቅስቃሴዎች ዳግመኛ እንዲመጣጠኑ አስገድድ"</string> <string name="force_resizable_activities_summary" msgid="2490382056981583062">"የዝርዝር ሰነድ እሴቶች ምንም ይሁኑ ምን ለበርካታ መስኮቶች ሁሉንም እንቅስቃሴዎች መጠናቸው የሚቀየሩ እንዲሆኑ ያደርጋቸዋል።"</string> - <string name="enable_freeform_support" msgid="8409932201445109106">"ነፃ ቅርጽ መስኮቶች (የቆየ) ያንቁ"</string> - <string name="enable_freeform_support_summary" msgid="2242481082356957934">"የሙከራ የቆዩ የነፃ ቅርጽ መስኮቶች ድጋፍን ያንቁ።"</string> + <string name="enable_freeform_support" msgid="7599125687603914253">"የነጻ ቅርጽ መስኮቶችን ያንቁ"</string> <string name="local_backup_password_title" msgid="4631017948933578709">"የዴስክቶፕ መጠባበቂያ ይለፍ ቃል"</string> <string name="local_backup_password_summary_none" msgid="7646898032616361714">"ዴስክቶፕ ሙሉ ምትኬዎች በአሁኑ ሰዓት አልተጠበቁም"</string> <string name="local_backup_password_summary_change" msgid="1707357670383995567">"የዴስክቶፕ ሙሉ ምትኬዎች የይለፍ ቃሉን ለመለወጥ ወይም ለማስወገድ ነካ ያድርጉ"</string> @@ -496,7 +495,8 @@ <string name="power_charging" msgid="6727132649743436802">"<xliff:g id="LEVEL">%1$s</xliff:g> - <xliff:g id="STATE">%2$s</xliff:g>"</string> <string name="power_remaining_charging_duration_only" msgid="8085099012811384899">"እስኪሞላ ድረስ <xliff:g id="TIME">%1$s</xliff:g> ይቀራል"</string> <string name="power_charging_duration" msgid="6127154952524919719">"<xliff:g id="LEVEL">%1$s</xliff:g> - እስኪሞላ ድረስ <xliff:g id="TIME">%2$s</xliff:g> ይቀራል"</string> - <string name="power_charging_limited" msgid="8202147604844938236">"<xliff:g id="LEVEL">%1$s</xliff:g> - ኃይል መሙላት እንዲተባ ተደርጓል"</string> + <!-- no translation found for power_charging_limited (4144004473976005214) --> + <skip /> <string name="power_charging_future_paused" msgid="1809543660923642799">"<xliff:g id="LEVEL">%1$s</xliff:g> - ኃይል በመሙላት ላይ"</string> <string name="power_fast_charging_duration_v2" msgid="3797735998640359490">"<xliff:g id="LEVEL">%1$s</xliff:g> - <xliff:g id="STATUS">%2$s</xliff:g> - እስከ <xliff:g id="TIME">%3$s</xliff:g> ድረስ ይሞላል"</string> <string name="power_charging_duration_v2" msgid="2938998284074003248">"<xliff:g id="LEVEL">%1$s</xliff:g> - እስከ <xliff:g id="TIME">%2$s</xliff:g> ሙሉ ለሙሉ ይሞላል"</string> diff --git a/packages/SettingsLib/res/values-ar/strings.xml b/packages/SettingsLib/res/values-ar/strings.xml index 287dfae33280..99abb2e520ba 100644 --- a/packages/SettingsLib/res/values-ar/strings.xml +++ b/packages/SettingsLib/res/values-ar/strings.xml @@ -430,8 +430,7 @@ <string name="force_allow_on_external_summary" msgid="8525425782530728238">"تأهيل أي تطبيق بحيث تتم كتابته على وحدة تخزين خارجية، بغض النظر عن قيم البيان"</string> <string name="force_resizable_activities" msgid="7143612144399959606">"فرض إمكانية تغيير حجم الأنشطة"</string> <string name="force_resizable_activities_summary" msgid="2490382056981583062">"السماح بتغيير حجم جميع الأنشطة لتناسب تعدد النوافذ، بغض النظر عن قيم البيان"</string> - <string name="enable_freeform_support" msgid="8409932201445109106">"تفعيل النوافذ الحرة (القديمة)"</string> - <string name="enable_freeform_support_summary" msgid="2242481082356957934">"تفعيل عرض النوافذ الحرة التجريبية القديمة"</string> + <string name="enable_freeform_support" msgid="7599125687603914253">"تفعيل النوافذ الحرة"</string> <string name="local_backup_password_title" msgid="4631017948933578709">"كلمة مرور احتياطية للكمبيوتر"</string> <string name="local_backup_password_summary_none" msgid="7646898032616361714">"النُسخ الاحتياطية الكاملة لسطح المكتب غير محمية في الوقت الحالي"</string> <string name="local_backup_password_summary_change" msgid="1707357670383995567">"انقر لتغيير كلمة مرور النسخ الاحتياطية الكاملة لسطح المكتب أو إزالتها."</string> @@ -496,7 +495,8 @@ <string name="power_charging" msgid="6727132649743436802">"<xliff:g id="LEVEL">%1$s</xliff:g> - <xliff:g id="STATE">%2$s</xliff:g>"</string> <string name="power_remaining_charging_duration_only" msgid="8085099012811384899">"يتبقّى <xliff:g id="TIME">%1$s</xliff:g> حتى اكتمال شحن البطارية"</string> <string name="power_charging_duration" msgid="6127154952524919719">"<xliff:g id="LEVEL">%1$s</xliff:g> - يتبقّى <xliff:g id="TIME">%2$s</xliff:g> حتى اكتمال شحن البطارية."</string> - <string name="power_charging_limited" msgid="8202147604844938236">"<xliff:g id="LEVEL">%1$s</xliff:g> - تم تحسين الشحن"</string> + <!-- no translation found for power_charging_limited (4144004473976005214) --> + <skip /> <string name="power_charging_future_paused" msgid="1809543660923642799">"<xliff:g id="LEVEL">%1$s</xliff:g>: جارٍ الشحن"</string> <string name="power_fast_charging_duration_v2" msgid="3797735998640359490">"<xliff:g id="LEVEL">%1$s</xliff:g> - <xliff:g id="STATUS">%2$s</xliff:g> - سيكتمل الشحن بحلول <xliff:g id="TIME">%3$s</xliff:g>"</string> <string name="power_charging_duration_v2" msgid="2938998284074003248">"<xliff:g id="LEVEL">%1$s</xliff:g> - سيكتمل الشحن بحلول <xliff:g id="TIME">%2$s</xliff:g>"</string> diff --git a/packages/SettingsLib/res/values-as/strings.xml b/packages/SettingsLib/res/values-as/strings.xml index da17f8007efd..38600f4a8c87 100644 --- a/packages/SettingsLib/res/values-as/strings.xml +++ b/packages/SettingsLib/res/values-as/strings.xml @@ -430,8 +430,7 @@ <string name="force_allow_on_external_summary" msgid="8525425782530728238">"মেনিফেষ্টৰ মান যিয়েই নহওক, বাহ্যিক ষ্ট’ৰেজত লিখিবলৈ যিকোনো এপক উপযুক্ত কৰি তোলে"</string> <string name="force_resizable_activities" msgid="7143612144399959606">"বলেৰে কাৰ্যকলাপসমূহৰ আকাৰ সলনি কৰিব পৰা কৰক"</string> <string name="force_resizable_activities_summary" msgid="2490382056981583062">"মেনিফেষ্টৰ মান যিয়েই নহওক, মাল্টি-ৱিণ্ডৰ বাবে আটাইবোৰ কাৰ্যকলাপৰ আকাৰ সলনি কৰিব পৰা কৰক।"</string> - <string name="enable_freeform_support" msgid="8409932201445109106">"ফ্ৰীফৰ্ম ৱিণ্ড’ সক্ষম কৰ (লিগেচী)"</string> - <string name="enable_freeform_support_summary" msgid="2242481082356957934">"পৰীক্ষামূলক লিগেচী ফ্ৰীফৰ্ম ৱিণ্ড’ৰ সমৰ্থন সক্ষম কৰক।"</string> + <string name="enable_freeform_support" msgid="7599125687603914253">"ফ্ৰিফৰ্ম ৱিণ্ড\'জ সক্ষম কৰক"</string> <string name="local_backup_password_title" msgid="4631017948933578709">"ডেস্কটপ বেকআপ পাছৱৰ্ড"</string> <string name="local_backup_password_summary_none" msgid="7646898032616361714">"ডেস্কটপৰ পূৰ্ণ বেকআপ এতিয়ালৈকে সংৰক্ষিত অৱস্থাত নাই"</string> <string name="local_backup_password_summary_change" msgid="1707357670383995567">"ডেস্কটপ সম্পূৰ্ণ বেকআপৰ বাবে পাছৱৰ্ডটো সলনি কৰিবলৈ বা আঁতৰাবলৈ টিপক"</string> @@ -496,7 +495,8 @@ <string name="power_charging" msgid="6727132649743436802">"<xliff:g id="LEVEL">%1$s</xliff:g> - <xliff:g id="STATE">%2$s</xliff:g>"</string> <string name="power_remaining_charging_duration_only" msgid="8085099012811384899">"সম্পূৰ্ণ হ’বলৈ <xliff:g id="TIME">%1$s</xliff:g> বাকী আছে"</string> <string name="power_charging_duration" msgid="6127154952524919719">"সম্পূৰ্ণ হ’বলৈ <xliff:g id="LEVEL">%1$s</xliff:g> - <xliff:g id="TIME">%2$s</xliff:g> বাকী আছে"</string> - <string name="power_charging_limited" msgid="8202147604844938236">"<xliff:g id="LEVEL">%1$s</xliff:g> - চাৰ্জিং অপ্টিমাইজ কৰা হৈছে"</string> + <!-- no translation found for power_charging_limited (4144004473976005214) --> + <skip /> <string name="power_charging_future_paused" msgid="1809543660923642799">"<xliff:g id="LEVEL">%1$s</xliff:g> ‑ চাৰ্জ হৈ আছে"</string> <string name="power_fast_charging_duration_v2" msgid="3797735998640359490">"<xliff:g id="LEVEL">%1$s</xliff:g> - <xliff:g id="STATUS">%2$s</xliff:g> - <xliff:g id="TIME">%3$s</xliff:g>ৰ ভিতৰত সম্পূৰ্ণ হ’ব"</string> <string name="power_charging_duration_v2" msgid="2938998284074003248">"<xliff:g id="LEVEL">%1$s</xliff:g> - <xliff:g id="TIME">%2$s</xliff:g>ৰ ভিতৰত সম্পূৰ্ণৰূপে চাৰ্জ হ’ব"</string> diff --git a/packages/SettingsLib/res/values-az/strings.xml b/packages/SettingsLib/res/values-az/strings.xml index 5ae1c6e291fa..d41cf0e3f80c 100644 --- a/packages/SettingsLib/res/values-az/strings.xml +++ b/packages/SettingsLib/res/values-az/strings.xml @@ -430,8 +430,7 @@ <string name="force_allow_on_external_summary" msgid="8525425782530728238">"Manifest dəyərindən asılı olmayaraq tətbiqlərin xarici daşıyıcılarda saxlanmasına icazə verilsin"</string> <string name="force_resizable_activities" msgid="7143612144399959606">"Çoxpəncərəli rejimdə ölçü dəyişdirilməsi"</string> <string name="force_resizable_activities_summary" msgid="2490382056981583062">"Manifest dəyərindən asılı olmayaraq çoxpəncərəli rejimdə pəncərə ölçüsünün dəyişdirilməsinə icazə verilsin"</string> - <string name="enable_freeform_support" msgid="8409932201445109106">"İxtiyari formada pəncərələri (köhnə) aktivləşdirin"</string> - <string name="enable_freeform_support_summary" msgid="2242481082356957934">"Təcrübi köhnə ixtiyari formada pəncərələr üçün dəstəyi aktivləşdirin."</string> + <string name="enable_freeform_support" msgid="7599125687603914253">"İxtiyari formada pəncərə yaradılsın"</string> <string name="local_backup_password_title" msgid="4631017948933578709">"Masaüstü rezerv parolu"</string> <string name="local_backup_password_summary_none" msgid="7646898032616361714">"Masaüstü tam rezervlər hazırda qorunmayıblar."</string> <string name="local_backup_password_summary_change" msgid="1707357670383995567">"Masaüstünün tam rezerv kopyalanması üçün parolu dəyişmək və ya silmək üçün basın"</string> @@ -496,7 +495,8 @@ <string name="power_charging" msgid="6727132649743436802">"<xliff:g id="LEVEL">%1$s</xliff:g> - <xliff:g id="STATE">%2$s</xliff:g>"</string> <string name="power_remaining_charging_duration_only" msgid="8085099012811384899">"Tam şarj edilənədək <xliff:g id="TIME">%1$s</xliff:g> qalıb"</string> <string name="power_charging_duration" msgid="6127154952524919719">"<xliff:g id="LEVEL">%1$s</xliff:g> - tam şarj edilənədək <xliff:g id="TIME">%2$s</xliff:g> qalıb"</string> - <string name="power_charging_limited" msgid="8202147604844938236">"<xliff:g id="LEVEL">%1$s</xliff:g> - Şarj optimallaşdırılıb"</string> + <!-- no translation found for power_charging_limited (4144004473976005214) --> + <skip /> <string name="power_charging_future_paused" msgid="1809543660923642799">"<xliff:g id="LEVEL">%1$s</xliff:g> - Şarj edilir"</string> <string name="power_fast_charging_duration_v2" msgid="3797735998640359490">"<xliff:g id="LEVEL">%1$s</xliff:g> - <xliff:g id="STATUS">%2$s</xliff:g> - <xliff:g id="TIME">%3$s</xliff:g> radələrinə qədər tam dolacaq"</string> <string name="power_charging_duration_v2" msgid="2938998284074003248">"<xliff:g id="LEVEL">%1$s</xliff:g> - <xliff:g id="TIME">%2$s</xliff:g> radələrinə qədər tam dolacaq"</string> diff --git a/packages/SettingsLib/res/values-b+sr+Latn/strings.xml b/packages/SettingsLib/res/values-b+sr+Latn/strings.xml index 2b92c52ff3fd..c576af5135b2 100644 --- a/packages/SettingsLib/res/values-b+sr+Latn/strings.xml +++ b/packages/SettingsLib/res/values-b+sr+Latn/strings.xml @@ -430,8 +430,7 @@ <string name="force_allow_on_external_summary" msgid="8525425782530728238">"Omogućava upisivanje svih aplikacija u spoljnu memoriju, bez obzira na vrednosti manifesta"</string> <string name="force_resizable_activities" msgid="7143612144399959606">"Prinudno omogući promenu veličine aktivnosti"</string> <string name="force_resizable_activities_summary" msgid="2490382056981583062">"Omogućava promenu veličine svih aktivnosti za režim sa više prozora, bez obzira na vrednosti manifesta."</string> - <string name="enable_freeform_support" msgid="8409932201445109106">"Omogući prozore proizvoljnog formata (zastarelo)"</string> - <string name="enable_freeform_support_summary" msgid="2242481082356957934">"Omogućava podršku za zastarele eksperimentalne prozore proizvoljnog formata."</string> + <string name="enable_freeform_support" msgid="7599125687603914253">"Omogući prozore proizvoljnog formata"</string> <string name="local_backup_password_title" msgid="4631017948933578709">"Lozinka rezervne kopije za računar"</string> <string name="local_backup_password_summary_none" msgid="7646898032616361714">"Rezervne kopije čitavog sistema trenutno nisu zaštićene"</string> <string name="local_backup_password_summary_change" msgid="1707357670383995567">"Dodirnite da biste promenili ili uklonili lozinku za pravljenje rezervnih kopija čitavog sistema na računaru"</string> @@ -496,7 +495,8 @@ <string name="power_charging" msgid="6727132649743436802">"<xliff:g id="LEVEL">%1$s</xliff:g> – <xliff:g id="STATE">%2$s</xliff:g>"</string> <string name="power_remaining_charging_duration_only" msgid="8085099012811384899">"<xliff:g id="TIME">%1$s</xliff:g> do kraja punjenja"</string> <string name="power_charging_duration" msgid="6127154952524919719">"<xliff:g id="LEVEL">%1$s</xliff:g> – <xliff:g id="TIME">%2$s</xliff:g> do kraja punjenja"</string> - <string name="power_charging_limited" msgid="8202147604844938236">"<xliff:g id="LEVEL">%1$s</xliff:g> – punjenje je optimizovano"</string> + <!-- no translation found for power_charging_limited (4144004473976005214) --> + <skip /> <string name="power_charging_future_paused" msgid="1809543660923642799">"<xliff:g id="LEVEL">%1$s</xliff:g> – Punjenje"</string> <string name="power_fast_charging_duration_v2" msgid="3797735998640359490">"<xliff:g id="LEVEL">%1$s</xliff:g> – <xliff:g id="STATUS">%2$s</xliff:g> – Potpuno napunjeno do <xliff:g id="TIME">%3$s</xliff:g>"</string> <string name="power_charging_duration_v2" msgid="2938998284074003248">"<xliff:g id="LEVEL">%1$s</xliff:g> – Potpuno napunjeno do <xliff:g id="TIME">%2$s</xliff:g>"</string> diff --git a/packages/SettingsLib/res/values-be/strings.xml b/packages/SettingsLib/res/values-be/strings.xml index e676fdf97555..9fd2af3d6f60 100644 --- a/packages/SettingsLib/res/values-be/strings.xml +++ b/packages/SettingsLib/res/values-be/strings.xml @@ -430,8 +430,7 @@ <string name="force_allow_on_external_summary" msgid="8525425782530728238">"Робіць любую праграму даступнай для запісу ў знешняе сховішча, незалежна ад значэнняў маніфеста"</string> <string name="force_resizable_activities" msgid="7143612144399959606">"Зрабіць вокны дзеянняў даступнымі для змены памеру"</string> <string name="force_resizable_activities_summary" msgid="2490382056981583062">"Зрабіць усе віды дзейнасці даступнымі для змены памеру ў рэжыме некалькіх вокнаў, незалежна ад значэнняў маніфеста."</string> - <string name="enable_freeform_support" msgid="8409932201445109106">"Уключыць адвольную форму вокнаў (устарэлая налада)"</string> - <string name="enable_freeform_support_summary" msgid="2242481082356957934">"Уключыць падтрымку для эксперыментальнай адвольнай формы вокнаў (устарэлая налада)."</string> + <string name="enable_freeform_support" msgid="7599125687603914253">"Уключыць адвольную форму вокнаў"</string> <string name="local_backup_password_title" msgid="4631017948933578709">"Пароль для рэз. копіі ПК"</string> <string name="local_backup_password_summary_none" msgid="7646898032616361714">"Поўнае рэзервовае капіраванне працоўнага стала зараз не абаронена"</string> <string name="local_backup_password_summary_change" msgid="1707357670383995567">"Краніце, каб змяніць або выдаліць пароль для поўнага рэзервовага капіравання працоўнага стала"</string> @@ -496,7 +495,8 @@ <string name="power_charging" msgid="6727132649743436802">"<xliff:g id="LEVEL">%1$s</xliff:g> – <xliff:g id="STATE">%2$s</xliff:g>"</string> <string name="power_remaining_charging_duration_only" msgid="8085099012811384899">"Да поўнай зарадкі засталося <xliff:g id="TIME">%1$s</xliff:g>"</string> <string name="power_charging_duration" msgid="6127154952524919719">"<xliff:g id="LEVEL">%1$s</xliff:g> – да поўнай зарадкі засталося: <xliff:g id="TIME">%2$s</xliff:g>"</string> - <string name="power_charging_limited" msgid="8202147604844938236">"<xliff:g id="LEVEL">%1$s</xliff:g> – Зарадка аптымізавана"</string> + <!-- no translation found for power_charging_limited (4144004473976005214) --> + <skip /> <string name="power_charging_future_paused" msgid="1809543660923642799">"<xliff:g id="LEVEL">%1$s</xliff:g> – зараджаецца"</string> <string name="power_fast_charging_duration_v2" msgid="3797735998640359490">"<xliff:g id="LEVEL">%1$s</xliff:g> – <xliff:g id="STATUS">%2$s</xliff:g> – Прылада зарадзіцца поўнасцю да <xliff:g id="TIME">%3$s</xliff:g>"</string> <string name="power_charging_duration_v2" msgid="2938998284074003248">"<xliff:g id="LEVEL">%1$s</xliff:g> – Прылада зарадзіцца поўнасцю да <xliff:g id="TIME">%2$s</xliff:g>"</string> diff --git a/packages/SettingsLib/res/values-bg/strings.xml b/packages/SettingsLib/res/values-bg/strings.xml index c64e2ead6952..462535b5eee5 100644 --- a/packages/SettingsLib/res/values-bg/strings.xml +++ b/packages/SettingsLib/res/values-bg/strings.xml @@ -430,8 +430,7 @@ <string name="force_allow_on_external_summary" msgid="8525425782530728238">"Всички приложения ще отговарят на условията да бъдат записвани във външното хранилище независимо от стойностите в манифеста"</string> <string name="force_resizable_activities" msgid="7143612144399959606">"Възможност за преоразмеряване на активностите"</string> <string name="force_resizable_activities_summary" msgid="2490382056981583062">"Дава възможност за преоразмеряване на всички активности в режима за няколко прозореца независимо от стойностите в манифеста."</string> - <string name="enable_freeform_support" msgid="8409932201445109106">"Актив. на прозорците в свободна форма (наследени)"</string> - <string name="enable_freeform_support_summary" msgid="2242481082356957934">"Активиране на поддръжката за експерименталните наследени прозорци в свободна форма."</string> + <string name="enable_freeform_support" msgid="7599125687603914253">"Активиране на прозорците в свободна форма"</string> <string name="local_backup_password_title" msgid="4631017948933578709">"Парола за резервни копия"</string> <string name="local_backup_password_summary_none" msgid="7646898032616361714">"Понастоящем пълните резервни копия за настолен компютър не са защитени"</string> <string name="local_backup_password_summary_change" msgid="1707357670383995567">"Докоснете, за да промените или премахнете паролата за пълни резервни копия на настолния компютър"</string> @@ -496,7 +495,8 @@ <string name="power_charging" msgid="6727132649743436802">"<xliff:g id="LEVEL">%1$s</xliff:g> – <xliff:g id="STATE">%2$s</xliff:g>"</string> <string name="power_remaining_charging_duration_only" msgid="8085099012811384899">"Оставащо време до пълно зареждане: <xliff:g id="TIME">%1$s</xliff:g>"</string> <string name="power_charging_duration" msgid="6127154952524919719">"<xliff:g id="LEVEL">%1$s</xliff:g> – Оставащо време до пълно зареждане: <xliff:g id="TIME">%2$s</xliff:g>"</string> - <string name="power_charging_limited" msgid="8202147604844938236">"<xliff:g id="LEVEL">%1$s</xliff:g> – Зареждането е оптимизирано"</string> + <!-- no translation found for power_charging_limited (4144004473976005214) --> + <skip /> <string name="power_charging_future_paused" msgid="1809543660923642799">"<xliff:g id="LEVEL">%1$s</xliff:g> – зарежда се"</string> <string name="power_fast_charging_duration_v2" msgid="3797735998640359490">"<xliff:g id="LEVEL">%1$s</xliff:g> – <xliff:g id="STATUS">%2$s</xliff:g> – ще се зареди напълно до <xliff:g id="TIME">%3$s</xliff:g>"</string> <string name="power_charging_duration_v2" msgid="2938998284074003248">"<xliff:g id="LEVEL">%1$s</xliff:g> – ще се зареди напълно до <xliff:g id="TIME">%2$s</xliff:g>"</string> diff --git a/packages/SettingsLib/res/values-bn/strings.xml b/packages/SettingsLib/res/values-bn/strings.xml index 531795ab5cc9..cd53b673f860 100644 --- a/packages/SettingsLib/res/values-bn/strings.xml +++ b/packages/SettingsLib/res/values-bn/strings.xml @@ -430,8 +430,7 @@ <string name="force_allow_on_external_summary" msgid="8525425782530728238">"ম্যানিফেস্ট মানের নির্বিশেষে যেকোনও অ্যাপকে এক্সটারনাল স্টোরেজে ইনস্টল করার উপযুক্ত বানায়"</string> <string name="force_resizable_activities" msgid="7143612144399959606">"আকার পরিবর্তনযোগ্য করার জন্য ক্রিয়াকলাপগুলিকে জোর করুন"</string> <string name="force_resizable_activities_summary" msgid="2490382056981583062">"ম্যানিফেস্ট মানগুলির নির্বিশেষে মাল্টি-উইন্ডোর জন্য সমস্ত ক্রিয়াকলাপগুলির আকার পরিবর্তনযোগ্য করুন৷"</string> - <string name="enable_freeform_support" msgid="8409932201445109106">"ফ্রিফর্ম উইন্ডো (লিগ্যাসি) চালু করুন"</string> - <string name="enable_freeform_support_summary" msgid="2242481082356957934">"এক্সপেরিমেন্টাল ফ্রিফর্ম উইন্ডোর জন্য সহায়তা চালু করুন।"</string> + <string name="enable_freeform_support" msgid="7599125687603914253">"ফ্রি-ফর্ম উইন্ডো চালু করুন"</string> <string name="local_backup_password_title" msgid="4631017948933578709">"ডেস্কটপ ব্যাকআপ পাসওয়ার্ড"</string> <string name="local_backup_password_summary_none" msgid="7646898032616361714">"ডেস্কটপ পূর্ণ ব্যাকআপ বর্তমানে সুরক্ষিত নয়"</string> <string name="local_backup_password_summary_change" msgid="1707357670383995567">"ডেস্কটপের সম্পূর্ণ ব্যাকআপের পাসওয়ার্ডটি পরিবর্তন করতে বা মুছে ফেলতে আলতো চাপুন"</string> @@ -496,7 +495,8 @@ <string name="power_charging" msgid="6727132649743436802">"<xliff:g id="LEVEL">%1$s</xliff:g> - <xliff:g id="STATE">%2$s</xliff:g>"</string> <string name="power_remaining_charging_duration_only" msgid="8085099012811384899">"<xliff:g id="TIME">%1$s</xliff:g>-এ ব্যাটারি পুরো চার্জ হয়ে যাবে"</string> <string name="power_charging_duration" msgid="6127154952524919719">"<xliff:g id="LEVEL">%1$s</xliff:g> - <xliff:g id="TIME">%2$s</xliff:g>-এ ব্যাটারি পুরো চার্জ হয়ে যাবে"</string> - <string name="power_charging_limited" msgid="8202147604844938236">"<xliff:g id="LEVEL">%1$s</xliff:g> - চার্জিং অপ্টিমাইজ করা হয়েছে"</string> + <!-- no translation found for power_charging_limited (4144004473976005214) --> + <skip /> <string name="power_charging_future_paused" msgid="1809543660923642799">"<xliff:g id="LEVEL">%1$s</xliff:g> - চার্জ করা হচ্ছে"</string> <string name="power_fast_charging_duration_v2" msgid="3797735998640359490">"<xliff:g id="LEVEL">%1$s</xliff:g> - <xliff:g id="STATUS">%2$s</xliff:g> - <xliff:g id="TIME">%3$s</xliff:g>-এর মধ্যে পুরো চার্জ হয়ে যাবে"</string> <string name="power_charging_duration_v2" msgid="2938998284074003248">"<xliff:g id="LEVEL">%1$s</xliff:g> - <xliff:g id="TIME">%2$s</xliff:g>-এর মধ্যে পুরো চার্জ হয়ে যাবে"</string> diff --git a/packages/SettingsLib/res/values-bs/strings.xml b/packages/SettingsLib/res/values-bs/strings.xml index 93b4ffb2d0da..5e35f1a991a2 100644 --- a/packages/SettingsLib/res/values-bs/strings.xml +++ b/packages/SettingsLib/res/values-bs/strings.xml @@ -430,8 +430,7 @@ <string name="force_allow_on_external_summary" msgid="8525425782530728238">"Omogućava upisivanje svih aplikacija u vanjsku pohranu, bez obzira na prikazane vrijednosti"</string> <string name="force_resizable_activities" msgid="7143612144399959606">"Nametni aktivnostima mijenjanje veličina"</string> <string name="force_resizable_activities_summary" msgid="2490382056981583062">"Omogućava mijenjanje veličine svih aktivnosti za prikaz s više prozora, bez obzira na prikazane vrijednosti"</string> - <string name="enable_freeform_support" msgid="8409932201445109106">"Omogući prilagodljive prozore (staro)"</string> - <string name="enable_freeform_support_summary" msgid="2242481082356957934">"Omogućite podršku za eksperimentalne stare prilagodljive prozore."</string> + <string name="enable_freeform_support" msgid="7599125687603914253">"Omogući prozore nepravilnih oblika"</string> <string name="local_backup_password_title" msgid="4631017948933578709">"Lozinka sigurnosne kopije za računar"</string> <string name="local_backup_password_summary_none" msgid="7646898032616361714">"Potpune sigurnosne kopije za računare trenutno nisu zaštićene"</string> <string name="local_backup_password_summary_change" msgid="1707357670383995567">"Dodirnite da promijenite ili uklonite lozinku za potpune rezervne kopije s radne površine"</string> @@ -496,7 +495,8 @@ <string name="power_charging" msgid="6727132649743436802">"<xliff:g id="LEVEL">%1$s</xliff:g> – <xliff:g id="STATE">%2$s</xliff:g>"</string> <string name="power_remaining_charging_duration_only" msgid="8085099012811384899">"<xliff:g id="TIME">%1$s</xliff:g> do potpune napunjenosti"</string> <string name="power_charging_duration" msgid="6127154952524919719">"<xliff:g id="LEVEL">%1$s</xliff:g> – <xliff:g id="TIME">%2$s</xliff:g> do potpune napunjenosti"</string> - <string name="power_charging_limited" msgid="8202147604844938236">"<xliff:g id="LEVEL">%1$s</xliff:g> – punjenje je optimizirano"</string> + <!-- no translation found for power_charging_limited (4144004473976005214) --> + <skip /> <string name="power_charging_future_paused" msgid="1809543660923642799">"<xliff:g id="LEVEL">%1$s</xliff:g> – punjenje"</string> <string name="power_fast_charging_duration_v2" msgid="3797735998640359490">"<xliff:g id="LEVEL">%1$s</xliff:g> – <xliff:g id="STATUS">%2$s</xliff:g> – Napunit će se do <xliff:g id="TIME">%3$s</xliff:g>"</string> <string name="power_charging_duration_v2" msgid="2938998284074003248">"<xliff:g id="LEVEL">%1$s</xliff:g> – Potpuno napunjeno do <xliff:g id="TIME">%2$s</xliff:g>"</string> diff --git a/packages/SettingsLib/res/values-ca/strings.xml b/packages/SettingsLib/res/values-ca/strings.xml index 0e6b3d8651c2..18e8720ec01f 100644 --- a/packages/SettingsLib/res/values-ca/strings.xml +++ b/packages/SettingsLib/res/values-ca/strings.xml @@ -430,8 +430,7 @@ <string name="force_allow_on_external_summary" msgid="8525425782530728238">"Permet que qualsevol aplicació es pugui escriure en un dispositiu d’emmagatzematge extern, independentment dels valors del manifest"</string> <string name="force_resizable_activities" msgid="7143612144399959606">"Força l\'ajust de la mida de les activitats"</string> <string name="force_resizable_activities_summary" msgid="2490382056981583062">"Permet ajustar la mida de totes les activitats per al mode multifinestra, independentment dels valors del manifest"</string> - <string name="enable_freeform_support" msgid="8409932201445109106">"Activa les finestres amb format lliure (heretat)"</string> - <string name="enable_freeform_support_summary" msgid="2242481082356957934">"Activa la compatibilitat amb les finestres de format lliure heretades i experimentals."</string> + <string name="enable_freeform_support" msgid="7599125687603914253">"Activa les finestres amb format lliure"</string> <string name="local_backup_password_title" msgid="4631017948933578709">"Contrasenya per a còpies d\'ordinador"</string> <string name="local_backup_password_summary_none" msgid="7646898032616361714">"Les còpies de seguretat completes d\'ordinador no estan protegides"</string> <string name="local_backup_password_summary_change" msgid="1707357670383995567">"Toca per canviar o suprimir la contrasenya per a les còpies de seguretat completes de l\'ordinador"</string> @@ -496,7 +495,8 @@ <string name="power_charging" msgid="6727132649743436802">"<xliff:g id="LEVEL">%1$s</xliff:g>: <xliff:g id="STATE">%2$s</xliff:g>"</string> <string name="power_remaining_charging_duration_only" msgid="8085099012811384899">"<xliff:g id="TIME">%1$s</xliff:g> per completar la càrrega"</string> <string name="power_charging_duration" msgid="6127154952524919719">"<xliff:g id="LEVEL">%1$s</xliff:g>: <xliff:g id="TIME">%2$s</xliff:g> per completar la càrrega"</string> - <string name="power_charging_limited" msgid="8202147604844938236">"<xliff:g id="LEVEL">%1$s</xliff:g>: càrrega optimitzada"</string> + <!-- no translation found for power_charging_limited (4144004473976005214) --> + <skip /> <string name="power_charging_future_paused" msgid="1809543660923642799">"<xliff:g id="LEVEL">%1$s</xliff:g>: s\'està carregant"</string> <string name="power_fast_charging_duration_v2" msgid="3797735998640359490">"<xliff:g id="LEVEL">%1$s</xliff:g> - <xliff:g id="STATUS">%2$s</xliff:g> - Càrrega completa a les <xliff:g id="TIME">%3$s</xliff:g>"</string> <string name="power_charging_duration_v2" msgid="2938998284074003248">"<xliff:g id="LEVEL">%1$s</xliff:g> - Càrrega completa a les <xliff:g id="TIME">%2$s</xliff:g>"</string> diff --git a/packages/SettingsLib/res/values-cs/strings.xml b/packages/SettingsLib/res/values-cs/strings.xml index b04c9080ac46..7ca98f76fc8b 100644 --- a/packages/SettingsLib/res/values-cs/strings.xml +++ b/packages/SettingsLib/res/values-cs/strings.xml @@ -430,8 +430,7 @@ <string name="force_allow_on_external_summary" msgid="8525425782530728238">"Každou aplikaci bude možné zapsat do externího úložiště, bez ohledu na hodnoty manifestu"</string> <string name="force_resizable_activities" msgid="7143612144399959606">"Vynutit možnost změny velikosti aktivit"</string> <string name="force_resizable_activities_summary" msgid="2490382056981583062">"Umožní změnu velikosti všech aktivit na několik oken (bez ohledu na hodnoty manifestu)"</string> - <string name="enable_freeform_support" msgid="8409932201445109106">"Aktivovat okna s volným tvarem (starší nastavení)"</string> - <string name="enable_freeform_support_summary" msgid="2242481082356957934">"Aktivuje podporu starších experimentálních oken s volným tvarem."</string> + <string name="enable_freeform_support" msgid="7599125687603914253">"Aktivovat okna s volným tvarem"</string> <string name="local_backup_password_title" msgid="4631017948933578709">"Heslo pro zálohy v počítači"</string> <string name="local_backup_password_summary_none" msgid="7646898032616361714">"Úplné zálohy v počítači nejsou v současné době chráněny"</string> <string name="local_backup_password_summary_change" msgid="1707357670383995567">"Tuto možnost vyberte, chcete-li změnit nebo odebrat heslo pro úplné zálohy do počítače"</string> @@ -496,7 +495,8 @@ <string name="power_charging" msgid="6727132649743436802">"<xliff:g id="LEVEL">%1$s</xliff:g> – <xliff:g id="STATE">%2$s</xliff:g>"</string> <string name="power_remaining_charging_duration_only" msgid="8085099012811384899">"<xliff:g id="TIME">%1$s</xliff:g> do úplného nabití"</string> <string name="power_charging_duration" msgid="6127154952524919719">"<xliff:g id="LEVEL">%1$s</xliff:g> – <xliff:g id="TIME">%2$s</xliff:g> do úplného nabití"</string> - <string name="power_charging_limited" msgid="8202147604844938236">"<xliff:g id="LEVEL">%1$s</xliff:g> – optimalizované nabíjení"</string> + <!-- no translation found for power_charging_limited (4144004473976005214) --> + <skip /> <string name="power_charging_future_paused" msgid="1809543660923642799">"<xliff:g id="LEVEL">%1$s</xliff:g> – Nabíjení"</string> <string name="power_fast_charging_duration_v2" msgid="3797735998640359490">"<xliff:g id="LEVEL">%1$s</xliff:g> – <xliff:g id="STATUS">%2$s</xliff:g> – Úplné nabití: <xliff:g id="TIME">%3$s</xliff:g>"</string> <string name="power_charging_duration_v2" msgid="2938998284074003248">"<xliff:g id="LEVEL">%1$s</xliff:g> – Úplné nabití: <xliff:g id="TIME">%2$s</xliff:g>"</string> diff --git a/packages/SettingsLib/res/values-da/strings.xml b/packages/SettingsLib/res/values-da/strings.xml index 6e526dbedde9..5564722239a5 100644 --- a/packages/SettingsLib/res/values-da/strings.xml +++ b/packages/SettingsLib/res/values-da/strings.xml @@ -430,8 +430,7 @@ <string name="force_allow_on_external_summary" msgid="8525425782530728238">"Gør det muligt at overføre enhver app til et eksternt lager uafhængigt af manifestværdier"</string> <string name="force_resizable_activities" msgid="7143612144399959606">"Gennemtving, at aktiviteter kan tilpasses"</string> <string name="force_resizable_activities_summary" msgid="2490382056981583062">"Tillad, at alle aktiviteter kan tilpasses flere vinduer uafhængigt af manifestværdier"</string> - <string name="enable_freeform_support" msgid="8409932201445109106">"Aktivér vinduer i frit format (forældet)"</string> - <string name="enable_freeform_support_summary" msgid="2242481082356957934">"Aktivér understøttelse af eksperimentelle forældede vinduer i frit format."</string> + <string name="enable_freeform_support" msgid="7599125687603914253">"Aktivér vinduer i frit format"</string> <string name="local_backup_password_title" msgid="4631017948933578709">"Kode til lokal sikkerhedskopi"</string> <string name="local_backup_password_summary_none" msgid="7646898032616361714">"Lokale komplette backups er i øjeblikket ikke beskyttet"</string> <string name="local_backup_password_summary_change" msgid="1707357670383995567">"Tryk for at skifte eller fjerne adgangskoden til fuld lokal sikkerhedskopiering"</string> @@ -496,7 +495,8 @@ <string name="power_charging" msgid="6727132649743436802">"<xliff:g id="LEVEL">%1$s</xliff:g> – <xliff:g id="STATE">%2$s</xliff:g>"</string> <string name="power_remaining_charging_duration_only" msgid="8085099012811384899">"Fuldt opladet om <xliff:g id="TIME">%1$s</xliff:g>"</string> <string name="power_charging_duration" msgid="6127154952524919719">"<xliff:g id="LEVEL">%1$s</xliff:g> – fuldt opladet om <xliff:g id="TIME">%2$s</xliff:g>"</string> - <string name="power_charging_limited" msgid="8202147604844938236">"<xliff:g id="LEVEL">%1$s</xliff:g> – opladning er optimeret"</string> + <!-- no translation found for power_charging_limited (4144004473976005214) --> + <skip /> <string name="power_charging_future_paused" msgid="1809543660923642799">"<xliff:g id="LEVEL">%1$s</xliff:g> – oplades"</string> <string name="power_fast_charging_duration_v2" msgid="3797735998640359490">"<xliff:g id="LEVEL">%1$s</xliff:g> – <xliff:g id="STATUS">%2$s</xliff:g> – Opladet senest kl. <xliff:g id="TIME">%3$s</xliff:g>"</string> <string name="power_charging_duration_v2" msgid="2938998284074003248">"<xliff:g id="LEVEL">%1$s</xliff:g> – Fuldt opladet senest kl. <xliff:g id="TIME">%2$s</xliff:g>"</string> diff --git a/packages/SettingsLib/res/values-de/strings.xml b/packages/SettingsLib/res/values-de/strings.xml index 504a9daa148a..2fd683d5990b 100644 --- a/packages/SettingsLib/res/values-de/strings.xml +++ b/packages/SettingsLib/res/values-de/strings.xml @@ -430,8 +430,7 @@ <string name="force_allow_on_external_summary" msgid="8525425782530728238">"Jede App kann, ungeachtet der Manifestwerte, in den externen Speicher geschrieben werden"</string> <string name="force_resizable_activities" msgid="7143612144399959606">"Aktivitätengröße darf immer angepasst werden"</string> <string name="force_resizable_activities_summary" msgid="2490382056981583062">"Die Größe aller Aktivitäten darf, ungeachtet der Manifestwerte, für die Mehrfensterdarstellung angepasst werden"</string> - <string name="enable_freeform_support" msgid="8409932201445109106">"Freiform-Fenster zulassen (Legacy)"</string> - <string name="enable_freeform_support_summary" msgid="2242481082356957934">"Unterstützung für experimentelle Legacy-Freiform-Fenster aktivieren."</string> + <string name="enable_freeform_support" msgid="7599125687603914253">"Freiform-Fenster zulassen"</string> <string name="local_backup_password_title" msgid="4631017948933578709">"Passwort für Desktop-Sicherung"</string> <string name="local_backup_password_summary_none" msgid="7646898032616361714">"Vollständige Desktop-Sicherungen sind momentan nicht passwortgeschützt"</string> <string name="local_backup_password_summary_change" msgid="1707357670383995567">"Zum Ändern oder Entfernen des Passworts für vollständige Desktop-Sicherungen tippen"</string> @@ -496,7 +495,8 @@ <string name="power_charging" msgid="6727132649743436802">"<xliff:g id="LEVEL">%1$s</xliff:g> – <xliff:g id="STATE">%2$s</xliff:g>"</string> <string name="power_remaining_charging_duration_only" msgid="8085099012811384899">"Voll in <xliff:g id="TIME">%1$s</xliff:g>"</string> <string name="power_charging_duration" msgid="6127154952524919719">"<xliff:g id="LEVEL">%1$s</xliff:g> – voll in <xliff:g id="TIME">%2$s</xliff:g>"</string> - <string name="power_charging_limited" msgid="8202147604844938236">"<xliff:g id="LEVEL">%1$s</xliff:g> – Laden wird optimiert"</string> + <!-- no translation found for power_charging_limited (4144004473976005214) --> + <skip /> <string name="power_charging_future_paused" msgid="1809543660923642799">"<xliff:g id="LEVEL">%1$s</xliff:g> – Wird geladen"</string> <string name="power_fast_charging_duration_v2" msgid="3797735998640359490">"<xliff:g id="LEVEL">%1$s</xliff:g> – <xliff:g id="STATUS">%2$s</xliff:g> – Vollständig geladen in <xliff:g id="TIME">%3$s</xliff:g>"</string> <string name="power_charging_duration_v2" msgid="2938998284074003248">"<xliff:g id="LEVEL">%1$s</xliff:g> – Vollständig geladen in <xliff:g id="TIME">%2$s</xliff:g>"</string> diff --git a/packages/SettingsLib/res/values-el/strings.xml b/packages/SettingsLib/res/values-el/strings.xml index cad445fa41f8..4fdea21294a9 100644 --- a/packages/SettingsLib/res/values-el/strings.xml +++ b/packages/SettingsLib/res/values-el/strings.xml @@ -430,8 +430,7 @@ <string name="force_allow_on_external_summary" msgid="8525425782530728238">"Κάνει κάθε εφαρμογή κατάλληλη για εγγραφή σε εξωτερικό αποθηκευτικό χώρο, ανεξάρτητα από τις τιμές του μανιφέστου"</string> <string name="force_resizable_activities" msgid="7143612144399959606">"Αναγκαστική δυνατότητα αλλαγής μεγέθους δραστηριοτήτων"</string> <string name="force_resizable_activities_summary" msgid="2490382056981583062">"Να έχουν όλες οι δραστηριότητες δυνατότητα αλλαγής μεγέθους για την προβολή πολλαπλών παραθύρων, ανεξάρτητα από τις τιμές του μανιφέστου."</string> - <string name="enable_freeform_support" msgid="8409932201445109106">"Ενεργ. παραθύρων ελεύθερης μορφής (παλαιού τύπου)"</string> - <string name="enable_freeform_support_summary" msgid="2242481082356957934">"Ενεργοποίηση υποστήριξης για πειραματικά παράθυρα ελεύθερης μορφής παλαιού τύπου."</string> + <string name="enable_freeform_support" msgid="7599125687603914253">"Ενεργοποίηση παραθύρων ελεύθερης μορφής"</string> <string name="local_backup_password_title" msgid="4631017948933578709">"Εφ/κός κωδικός desktop"</string> <string name="local_backup_password_summary_none" msgid="7646898032616361714">"Τα πλήρη αντίγραφα ασφαλείας επιφάνειας εργασίας δεν προστατεύονται αυτή τη στιγμή"</string> <string name="local_backup_password_summary_change" msgid="1707357670383995567">"Πατήστε για αλλαγή ή κατάργηση του κωδικού πρόσβασης για τα πλήρη αντίγραφα ασφαλείας επιφάνειας εργασίας"</string> @@ -496,7 +495,8 @@ <string name="power_charging" msgid="6727132649743436802">"<xliff:g id="LEVEL">%1$s</xliff:g> - <xliff:g id="STATE">%2$s</xliff:g>"</string> <string name="power_remaining_charging_duration_only" msgid="8085099012811384899">"Απομένουν <xliff:g id="TIME">%1$s</xliff:g> για πλήρη φόρτιση"</string> <string name="power_charging_duration" msgid="6127154952524919719">"<xliff:g id="LEVEL">%1$s</xliff:g> - Απομένουν <xliff:g id="TIME">%2$s</xliff:g> για πλήρη φόρτιση"</string> - <string name="power_charging_limited" msgid="8202147604844938236">"<xliff:g id="LEVEL">%1$s</xliff:g> - Η φόρτιση βελτιστοποιήθηκε"</string> + <!-- no translation found for power_charging_limited (4144004473976005214) --> + <skip /> <string name="power_charging_future_paused" msgid="1809543660923642799">"<xliff:g id="LEVEL">%1$s</xliff:g> ‑ Φόρτιση"</string> <string name="power_fast_charging_duration_v2" msgid="3797735998640359490">"<xliff:g id="LEVEL">%1$s</xliff:g> - <xliff:g id="STATUS">%2$s</xliff:g> - Πλήρης φόρτιση στις <xliff:g id="TIME">%3$s</xliff:g>"</string> <string name="power_charging_duration_v2" msgid="2938998284074003248">"<xliff:g id="LEVEL">%1$s</xliff:g> - Πλήρης φόρτιση στις <xliff:g id="TIME">%2$s</xliff:g>"</string> diff --git a/packages/SettingsLib/res/values-en-rAU/strings.xml b/packages/SettingsLib/res/values-en-rAU/strings.xml index ad436646c5e1..bcffe2c736ef 100644 --- a/packages/SettingsLib/res/values-en-rAU/strings.xml +++ b/packages/SettingsLib/res/values-en-rAU/strings.xml @@ -430,8 +430,7 @@ <string name="force_allow_on_external_summary" msgid="8525425782530728238">"Makes any app eligible to be written to external storage, regardless of manifest values"</string> <string name="force_resizable_activities" msgid="7143612144399959606">"Force activities to be resizeable"</string> <string name="force_resizable_activities_summary" msgid="2490382056981583062">"Make all activities resizeable for multi-window, regardless of manifest values."</string> - <string name="enable_freeform_support" msgid="8409932201445109106">"Enable freeform windows (legacy)"</string> - <string name="enable_freeform_support_summary" msgid="2242481082356957934">"Enable support for experimental legacy freeform windows."</string> + <string name="enable_freeform_support" msgid="7599125687603914253">"Enable freeform windows"</string> <string name="local_backup_password_title" msgid="4631017948933578709">"Desktop backup password"</string> <string name="local_backup_password_summary_none" msgid="7646898032616361714">"Desktop full backups aren\'t currently protected"</string> <string name="local_backup_password_summary_change" msgid="1707357670383995567">"Tap to change or remove the password for desktop full backups"</string> @@ -496,7 +495,8 @@ <string name="power_charging" msgid="6727132649743436802">"<xliff:g id="LEVEL">%1$s</xliff:g> - <xliff:g id="STATE">%2$s</xliff:g>"</string> <string name="power_remaining_charging_duration_only" msgid="8085099012811384899">"<xliff:g id="TIME">%1$s</xliff:g> left until full"</string> <string name="power_charging_duration" msgid="6127154952524919719">"<xliff:g id="LEVEL">%1$s</xliff:g> – <xliff:g id="TIME">%2$s</xliff:g> left until full"</string> - <string name="power_charging_limited" msgid="8202147604844938236">"<xliff:g id="LEVEL">%1$s</xliff:g> - Charging optimised"</string> + <!-- no translation found for power_charging_limited (4144004473976005214) --> + <skip /> <string name="power_charging_future_paused" msgid="1809543660923642799">"<xliff:g id="LEVEL">%1$s</xliff:g> – charging"</string> <string name="power_fast_charging_duration_v2" msgid="3797735998640359490">"<xliff:g id="LEVEL">%1$s</xliff:g> – <xliff:g id="STATUS">%2$s</xliff:g> – Full by <xliff:g id="TIME">%3$s</xliff:g>"</string> <string name="power_charging_duration_v2" msgid="2938998284074003248">"<xliff:g id="LEVEL">%1$s</xliff:g> - Fully charged by <xliff:g id="TIME">%2$s</xliff:g>"</string> diff --git a/packages/SettingsLib/res/values-en-rCA/strings.xml b/packages/SettingsLib/res/values-en-rCA/strings.xml index a77d6c66447d..df54ac1198a0 100644 --- a/packages/SettingsLib/res/values-en-rCA/strings.xml +++ b/packages/SettingsLib/res/values-en-rCA/strings.xml @@ -430,8 +430,7 @@ <string name="force_allow_on_external_summary" msgid="8525425782530728238">"Makes any app eligible to be written to external storage, regardless of manifest values"</string> <string name="force_resizable_activities" msgid="7143612144399959606">"Force activities to be resizable"</string> <string name="force_resizable_activities_summary" msgid="2490382056981583062">"Make all activities resizable for multi-window, regardless of manifest values."</string> - <string name="enable_freeform_support" msgid="8409932201445109106">"Enable freeform windows (legacy)"</string> - <string name="enable_freeform_support_summary" msgid="2242481082356957934">"Enable support for experimental legacy freeform windows."</string> + <string name="enable_freeform_support" msgid="7599125687603914253">"Enable freeform windows"</string> <string name="local_backup_password_title" msgid="4631017948933578709">"Desktop backup password"</string> <string name="local_backup_password_summary_none" msgid="7646898032616361714">"Desktop full backups aren’t currently protected"</string> <string name="local_backup_password_summary_change" msgid="1707357670383995567">"Tap to change or remove the password for desktop full backups"</string> @@ -496,7 +495,8 @@ <string name="power_charging" msgid="6727132649743436802">"<xliff:g id="LEVEL">%1$s</xliff:g> - <xliff:g id="STATE">%2$s</xliff:g>"</string> <string name="power_remaining_charging_duration_only" msgid="8085099012811384899">"<xliff:g id="TIME">%1$s</xliff:g> left until full"</string> <string name="power_charging_duration" msgid="6127154952524919719">"<xliff:g id="LEVEL">%1$s</xliff:g> - <xliff:g id="TIME">%2$s</xliff:g> left until full"</string> - <string name="power_charging_limited" msgid="8202147604844938236">"<xliff:g id="LEVEL">%1$s</xliff:g> - Charging optimized"</string> + <!-- no translation found for power_charging_limited (4144004473976005214) --> + <skip /> <string name="power_charging_future_paused" msgid="1809543660923642799">"<xliff:g id="LEVEL">%1$s</xliff:g> - Charging"</string> <string name="power_fast_charging_duration_v2" msgid="3797735998640359490">"<xliff:g id="LEVEL">%1$s</xliff:g> - <xliff:g id="STATUS">%2$s</xliff:g> - Full by <xliff:g id="TIME">%3$s</xliff:g>"</string> <string name="power_charging_duration_v2" msgid="2938998284074003248">"<xliff:g id="LEVEL">%1$s</xliff:g> - Fully charged by <xliff:g id="TIME">%2$s</xliff:g>"</string> @@ -661,7 +661,7 @@ <string name="guest_exit_dialog_title" msgid="1846494656849381804">"Exit guest mode?"</string> <string name="guest_exit_dialog_message" msgid="1743218864242719783">"This will delete apps and data from the current guest session"</string> <string name="grant_admin" msgid="4323199171790522574">"Yes, make them an admin"</string> - <string name="not_grant_admin" msgid="3557849576157702485">"No, dont make them an admin"</string> + <string name="not_grant_admin" msgid="3557849576157702485">"No, don\'t make them an admin"</string> <string name="guest_exit_dialog_button" msgid="1736401897067442044">"Exit"</string> <string name="guest_exit_dialog_title_non_ephemeral" msgid="7675327443743162986">"Save guest activity?"</string> <string name="guest_exit_dialog_message_non_ephemeral" msgid="223385323235719442">"You can save activity from the current session or delete all apps and data"</string> diff --git a/packages/SettingsLib/res/values-en-rGB/strings.xml b/packages/SettingsLib/res/values-en-rGB/strings.xml index ad436646c5e1..bcffe2c736ef 100644 --- a/packages/SettingsLib/res/values-en-rGB/strings.xml +++ b/packages/SettingsLib/res/values-en-rGB/strings.xml @@ -430,8 +430,7 @@ <string name="force_allow_on_external_summary" msgid="8525425782530728238">"Makes any app eligible to be written to external storage, regardless of manifest values"</string> <string name="force_resizable_activities" msgid="7143612144399959606">"Force activities to be resizeable"</string> <string name="force_resizable_activities_summary" msgid="2490382056981583062">"Make all activities resizeable for multi-window, regardless of manifest values."</string> - <string name="enable_freeform_support" msgid="8409932201445109106">"Enable freeform windows (legacy)"</string> - <string name="enable_freeform_support_summary" msgid="2242481082356957934">"Enable support for experimental legacy freeform windows."</string> + <string name="enable_freeform_support" msgid="7599125687603914253">"Enable freeform windows"</string> <string name="local_backup_password_title" msgid="4631017948933578709">"Desktop backup password"</string> <string name="local_backup_password_summary_none" msgid="7646898032616361714">"Desktop full backups aren\'t currently protected"</string> <string name="local_backup_password_summary_change" msgid="1707357670383995567">"Tap to change or remove the password for desktop full backups"</string> @@ -496,7 +495,8 @@ <string name="power_charging" msgid="6727132649743436802">"<xliff:g id="LEVEL">%1$s</xliff:g> - <xliff:g id="STATE">%2$s</xliff:g>"</string> <string name="power_remaining_charging_duration_only" msgid="8085099012811384899">"<xliff:g id="TIME">%1$s</xliff:g> left until full"</string> <string name="power_charging_duration" msgid="6127154952524919719">"<xliff:g id="LEVEL">%1$s</xliff:g> – <xliff:g id="TIME">%2$s</xliff:g> left until full"</string> - <string name="power_charging_limited" msgid="8202147604844938236">"<xliff:g id="LEVEL">%1$s</xliff:g> - Charging optimised"</string> + <!-- no translation found for power_charging_limited (4144004473976005214) --> + <skip /> <string name="power_charging_future_paused" msgid="1809543660923642799">"<xliff:g id="LEVEL">%1$s</xliff:g> – charging"</string> <string name="power_fast_charging_duration_v2" msgid="3797735998640359490">"<xliff:g id="LEVEL">%1$s</xliff:g> – <xliff:g id="STATUS">%2$s</xliff:g> – Full by <xliff:g id="TIME">%3$s</xliff:g>"</string> <string name="power_charging_duration_v2" msgid="2938998284074003248">"<xliff:g id="LEVEL">%1$s</xliff:g> - Fully charged by <xliff:g id="TIME">%2$s</xliff:g>"</string> diff --git a/packages/SettingsLib/res/values-en-rIN/strings.xml b/packages/SettingsLib/res/values-en-rIN/strings.xml index ad436646c5e1..bcffe2c736ef 100644 --- a/packages/SettingsLib/res/values-en-rIN/strings.xml +++ b/packages/SettingsLib/res/values-en-rIN/strings.xml @@ -430,8 +430,7 @@ <string name="force_allow_on_external_summary" msgid="8525425782530728238">"Makes any app eligible to be written to external storage, regardless of manifest values"</string> <string name="force_resizable_activities" msgid="7143612144399959606">"Force activities to be resizeable"</string> <string name="force_resizable_activities_summary" msgid="2490382056981583062">"Make all activities resizeable for multi-window, regardless of manifest values."</string> - <string name="enable_freeform_support" msgid="8409932201445109106">"Enable freeform windows (legacy)"</string> - <string name="enable_freeform_support_summary" msgid="2242481082356957934">"Enable support for experimental legacy freeform windows."</string> + <string name="enable_freeform_support" msgid="7599125687603914253">"Enable freeform windows"</string> <string name="local_backup_password_title" msgid="4631017948933578709">"Desktop backup password"</string> <string name="local_backup_password_summary_none" msgid="7646898032616361714">"Desktop full backups aren\'t currently protected"</string> <string name="local_backup_password_summary_change" msgid="1707357670383995567">"Tap to change or remove the password for desktop full backups"</string> @@ -496,7 +495,8 @@ <string name="power_charging" msgid="6727132649743436802">"<xliff:g id="LEVEL">%1$s</xliff:g> - <xliff:g id="STATE">%2$s</xliff:g>"</string> <string name="power_remaining_charging_duration_only" msgid="8085099012811384899">"<xliff:g id="TIME">%1$s</xliff:g> left until full"</string> <string name="power_charging_duration" msgid="6127154952524919719">"<xliff:g id="LEVEL">%1$s</xliff:g> – <xliff:g id="TIME">%2$s</xliff:g> left until full"</string> - <string name="power_charging_limited" msgid="8202147604844938236">"<xliff:g id="LEVEL">%1$s</xliff:g> - Charging optimised"</string> + <!-- no translation found for power_charging_limited (4144004473976005214) --> + <skip /> <string name="power_charging_future_paused" msgid="1809543660923642799">"<xliff:g id="LEVEL">%1$s</xliff:g> – charging"</string> <string name="power_fast_charging_duration_v2" msgid="3797735998640359490">"<xliff:g id="LEVEL">%1$s</xliff:g> – <xliff:g id="STATUS">%2$s</xliff:g> – Full by <xliff:g id="TIME">%3$s</xliff:g>"</string> <string name="power_charging_duration_v2" msgid="2938998284074003248">"<xliff:g id="LEVEL">%1$s</xliff:g> - Fully charged by <xliff:g id="TIME">%2$s</xliff:g>"</string> diff --git a/packages/SettingsLib/res/values-en-rXC/strings.xml b/packages/SettingsLib/res/values-en-rXC/strings.xml index 8d6520f992b2..fc4c8a0a0d1b 100644 --- a/packages/SettingsLib/res/values-en-rXC/strings.xml +++ b/packages/SettingsLib/res/values-en-rXC/strings.xml @@ -430,8 +430,7 @@ <string name="force_allow_on_external_summary" msgid="8525425782530728238">"Makes any app eligible to be written to external storage, regardless of manifest values"</string> <string name="force_resizable_activities" msgid="7143612144399959606">"Force activities to be resizable"</string> <string name="force_resizable_activities_summary" msgid="2490382056981583062">"Make all activities resizable for multi-window, regardless of manifest values."</string> - <string name="enable_freeform_support" msgid="8409932201445109106">"Enable freeform windows (legacy)"</string> - <string name="enable_freeform_support_summary" msgid="2242481082356957934">"Enable support for experimental legacy freeform windows."</string> + <string name="enable_freeform_support" msgid="7599125687603914253">"Enable freeform windows"</string> <string name="local_backup_password_title" msgid="4631017948933578709">"Desktop backup password"</string> <string name="local_backup_password_summary_none" msgid="7646898032616361714">"Desktop full backups aren’t currently protected"</string> <string name="local_backup_password_summary_change" msgid="1707357670383995567">"Tap to change or remove the password for desktop full backups"</string> @@ -496,7 +495,8 @@ <string name="power_charging" msgid="6727132649743436802">"<xliff:g id="LEVEL">%1$s</xliff:g> - <xliff:g id="STATE">%2$s</xliff:g>"</string> <string name="power_remaining_charging_duration_only" msgid="8085099012811384899">"<xliff:g id="TIME">%1$s</xliff:g> left until full"</string> <string name="power_charging_duration" msgid="6127154952524919719">"<xliff:g id="LEVEL">%1$s</xliff:g> - <xliff:g id="TIME">%2$s</xliff:g> left until full"</string> - <string name="power_charging_limited" msgid="8202147604844938236">"<xliff:g id="LEVEL">%1$s</xliff:g> - Charging optimized"</string> + <!-- no translation found for power_charging_limited (4144004473976005214) --> + <skip /> <string name="power_charging_future_paused" msgid="1809543660923642799">"<xliff:g id="LEVEL">%1$s</xliff:g> - Charging"</string> <string name="power_fast_charging_duration_v2" msgid="3797735998640359490">"<xliff:g id="LEVEL">%1$s</xliff:g> - <xliff:g id="STATUS">%2$s</xliff:g> - Full by <xliff:g id="TIME">%3$s</xliff:g>"</string> <string name="power_charging_duration_v2" msgid="2938998284074003248">"<xliff:g id="LEVEL">%1$s</xliff:g> - Fully charged by <xliff:g id="TIME">%2$s</xliff:g>"</string> diff --git a/packages/SettingsLib/res/values-es-rUS/strings.xml b/packages/SettingsLib/res/values-es-rUS/strings.xml index 8b228330cb6e..e146f494e1b4 100644 --- a/packages/SettingsLib/res/values-es-rUS/strings.xml +++ b/packages/SettingsLib/res/values-es-rUS/strings.xml @@ -430,8 +430,7 @@ <string name="force_allow_on_external_summary" msgid="8525425782530728238">"Cualquier app puede escribirse en un almacenamiento externo, sin importar los valores del manifiesto"</string> <string name="force_resizable_activities" msgid="7143612144399959606">"Forzar actividades para que cambien de tamaño"</string> <string name="force_resizable_activities_summary" msgid="2490382056981583062">"Permitir que todas las actividades puedan cambiar de tamaño para el modo multiventana, sin importar los valores del manifiesto."</string> - <string name="enable_freeform_support" msgid="8409932201445109106">"Habilitar ventanas de formato libre (heredado)"</string> - <string name="enable_freeform_support_summary" msgid="2242481082356957934">"Permitir la compatibilidad con ventanas de formato libre experimentales (heredado)"</string> + <string name="enable_freeform_support" msgid="7599125687603914253">"Habilitar ventanas de forma libre"</string> <string name="local_backup_password_title" msgid="4631017948933578709">"Contraseñas"</string> <string name="local_backup_password_summary_none" msgid="7646898032616361714">"Tus copias de seguridad de escritorio no están protegidas por contraseña"</string> <string name="local_backup_password_summary_change" msgid="1707357670383995567">"Presiona para cambiar o quitar la contraseña de las copias de seguridad completas de tu escritorio."</string> @@ -496,7 +495,8 @@ <string name="power_charging" msgid="6727132649743436802">"<xliff:g id="LEVEL">%1$s</xliff:g>: <xliff:g id="STATE">%2$s</xliff:g>"</string> <string name="power_remaining_charging_duration_only" msgid="8085099012811384899">"<xliff:g id="TIME">%1$s</xliff:g> para completar"</string> <string name="power_charging_duration" msgid="6127154952524919719">"<xliff:g id="LEVEL">%1$s</xliff:g> - <xliff:g id="TIME">%2$s</xliff:g> para completar"</string> - <string name="power_charging_limited" msgid="8202147604844938236">"<xliff:g id="LEVEL">%1$s</xliff:g> - Carga optimizada"</string> + <!-- no translation found for power_charging_limited (4144004473976005214) --> + <skip /> <string name="power_charging_future_paused" msgid="1809543660923642799">"<xliff:g id="LEVEL">%1$s</xliff:g> - Cargando"</string> <string name="power_fast_charging_duration_v2" msgid="3797735998640359490">"<xliff:g id="LEVEL">%1$s</xliff:g> - <xliff:g id="STATUS">%2$s</xliff:g> - Carga completa: <xliff:g id="TIME">%3$s</xliff:g>"</string> <string name="power_charging_duration_v2" msgid="2938998284074003248">"<xliff:g id="LEVEL">%1$s</xliff:g> - Carga completa: <xliff:g id="TIME">%2$s</xliff:g>"</string> diff --git a/packages/SettingsLib/res/values-es/strings.xml b/packages/SettingsLib/res/values-es/strings.xml index 961c06749aab..fdfb8444d66b 100644 --- a/packages/SettingsLib/res/values-es/strings.xml +++ b/packages/SettingsLib/res/values-es/strings.xml @@ -430,8 +430,7 @@ <string name="force_allow_on_external_summary" msgid="8525425782530728238">"Permite que cualquier aplicación se pueda escribir en un almacenamiento externo independientemente de los valores de manifiesto"</string> <string name="force_resizable_activities" msgid="7143612144399959606">"Forzar que las actividades puedan cambiar de tamaño"</string> <string name="force_resizable_activities_summary" msgid="2490382056981583062">"Permite que todas las actividades puedan cambiar de tamaño en multiventana independientemente de los valores de manifiesto"</string> - <string name="enable_freeform_support" msgid="8409932201445109106">"Habilitar ventanas de forma libre (antiguo)"</string> - <string name="enable_freeform_support_summary" msgid="2242481082356957934">"Habilita la compatibilidad con ventanas de forma libre antiguas y experimentales."</string> + <string name="enable_freeform_support" msgid="7599125687603914253">"Habilitar ventanas de forma libre"</string> <string name="local_backup_password_title" msgid="4631017948933578709">"Contraseña para copias de ordenador"</string> <string name="local_backup_password_summary_none" msgid="7646898032616361714">"Las copias de seguridad completas de ordenador no están protegidas"</string> <string name="local_backup_password_summary_change" msgid="1707357670383995567">"Toca para cambiar o quitar la contraseña de las copias de seguridad completas del escritorio"</string> @@ -496,7 +495,8 @@ <string name="power_charging" msgid="6727132649743436802">"<xliff:g id="LEVEL">%1$s</xliff:g> - <xliff:g id="STATE">%2$s</xliff:g>"</string> <string name="power_remaining_charging_duration_only" msgid="8085099012811384899">"<xliff:g id="TIME">%1$s</xliff:g> hasta la carga completa"</string> <string name="power_charging_duration" msgid="6127154952524919719">"<xliff:g id="LEVEL">%1$s</xliff:g> - <xliff:g id="TIME">%2$s</xliff:g> hasta la carga completa"</string> - <string name="power_charging_limited" msgid="8202147604844938236">"<xliff:g id="LEVEL">%1$s</xliff:g> - Carga optimizada"</string> + <!-- no translation found for power_charging_limited (4144004473976005214) --> + <skip /> <string name="power_charging_future_paused" msgid="1809543660923642799">"<xliff:g id="LEVEL">%1$s</xliff:g> ‑ Cargar"</string> <string name="power_fast_charging_duration_v2" msgid="3797735998640359490">"<xliff:g id="LEVEL">%1$s</xliff:g> - <xliff:g id="STATUS">%2$s</xliff:g> - Carga completa a las <xliff:g id="TIME">%3$s</xliff:g>"</string> <string name="power_charging_duration_v2" msgid="2938998284074003248">"<xliff:g id="LEVEL">%1$s</xliff:g> - Carga completa a las <xliff:g id="TIME">%2$s</xliff:g>"</string> diff --git a/packages/SettingsLib/res/values-et/strings.xml b/packages/SettingsLib/res/values-et/strings.xml index 70b436cf0249..cff38ebfcdc6 100644 --- a/packages/SettingsLib/res/values-et/strings.xml +++ b/packages/SettingsLib/res/values-et/strings.xml @@ -430,8 +430,7 @@ <string name="force_allow_on_external_summary" msgid="8525425782530728238">"Lubab mis tahes rakendusi kirjutada välisesse salvestusruumi manifesti väärtustest olenemata"</string> <string name="force_resizable_activities" msgid="7143612144399959606">"Muuda tegevuste suurused muudetavaks"</string> <string name="force_resizable_activities_summary" msgid="2490382056981583062">"Muudetakse kõigi tegevuste suurused mitme aknaga vaates muudetavaks (manifesti väärtustest olenemata)."</string> - <string name="enable_freeform_support" msgid="8409932201445109106">"Luba vabas vormis aknad (pärand)"</string> - <string name="enable_freeform_support_summary" msgid="2242481082356957934">"Lubatakse katseliste pärand vabas vormis akende tugi."</string> + <string name="enable_freeform_support" msgid="7599125687603914253">"Luba vabas vormis aknad"</string> <string name="local_backup_password_title" msgid="4631017948933578709">"Arvutivarunduse parool"</string> <string name="local_backup_password_summary_none" msgid="7646898032616361714">"Täielikud arvutivarundused pole praegu kaitstud"</string> <string name="local_backup_password_summary_change" msgid="1707357670383995567">"Puudutage täielike arvutivarunduste parooli muutmiseks või eemaldamiseks"</string> @@ -496,7 +495,8 @@ <string name="power_charging" msgid="6727132649743436802">"<xliff:g id="LEVEL">%1$s</xliff:g> – <xliff:g id="STATE">%2$s</xliff:g>"</string> <string name="power_remaining_charging_duration_only" msgid="8085099012811384899">"Täislaadimiseks kulub <xliff:g id="TIME">%1$s</xliff:g>"</string> <string name="power_charging_duration" msgid="6127154952524919719">"<xliff:g id="LEVEL">%1$s</xliff:g> – täislaadimiseks kulub <xliff:g id="TIME">%2$s</xliff:g>"</string> - <string name="power_charging_limited" msgid="8202147604844938236">"<xliff:g id="LEVEL">%1$s</xliff:g> – laadimine on optimeeritud"</string> + <!-- no translation found for power_charging_limited (4144004473976005214) --> + <skip /> <string name="power_charging_future_paused" msgid="1809543660923642799">"<xliff:g id="LEVEL">%1$s</xliff:g> – laadimine"</string> <string name="power_fast_charging_duration_v2" msgid="3797735998640359490">"<xliff:g id="LEVEL">%1$s</xliff:g> – <xliff:g id="STATUS">%2$s</xliff:g> – täis kell <xliff:g id="TIME">%3$s</xliff:g>"</string> <string name="power_charging_duration_v2" msgid="2938998284074003248">"<xliff:g id="LEVEL">%1$s</xliff:g> – aku saab täis kell <xliff:g id="TIME">%2$s</xliff:g>"</string> diff --git a/packages/SettingsLib/res/values-eu/strings.xml b/packages/SettingsLib/res/values-eu/strings.xml index 1c80af8bb65f..622055e17993 100644 --- a/packages/SettingsLib/res/values-eu/strings.xml +++ b/packages/SettingsLib/res/values-eu/strings.xml @@ -430,8 +430,7 @@ <string name="force_allow_on_external_summary" msgid="8525425782530728238">"Aplikazioek kanpoko memorian idatz dezakete, ezarritako balioak kontuan izan gabe"</string> <string name="force_resizable_activities" msgid="7143612144399959606">"Behartu jardueren tamaina doitu ahal izatera"</string> <string name="force_resizable_activities_summary" msgid="2490382056981583062">"Eman aukera jarduera guztien tamaina doitzeko, leiho batean baino gehiagotan erabili ahal izan daitezen, ezarritako balioak kontuan izan gabe"</string> - <string name="enable_freeform_support" msgid="8409932201445109106">"Gaitu estilo libreko leihoak (aurreko bertsiokoak)"</string> - <string name="enable_freeform_support_summary" msgid="2242481082356957934">"Onartu aurreko bertsioko estilo libreko leiho esperimentalak."</string> + <string name="enable_freeform_support" msgid="7599125687603914253">"Gaitu estilo libreko leihoak"</string> <string name="local_backup_password_title" msgid="4631017948933578709">"Babeskopien pasahitz lokala"</string> <string name="local_backup_password_summary_none" msgid="7646898032616361714">"Une honetan, ordenagailuko babeskopia osoak ez daude babestuta"</string> <string name="local_backup_password_summary_change" msgid="1707357670383995567">"Ordenagailuko eduki guztiaren babeskopia egiteko erabiltzen den pasahitza aldatzeko edo kentzeko, sakatu hau"</string> @@ -496,7 +495,8 @@ <string name="power_charging" msgid="6727132649743436802">"<xliff:g id="LEVEL">%1$s</xliff:g> - <xliff:g id="STATE">%2$s</xliff:g>"</string> <string name="power_remaining_charging_duration_only" msgid="8085099012811384899">"<xliff:g id="TIME">%1$s</xliff:g> guztiz kargatu arte"</string> <string name="power_charging_duration" msgid="6127154952524919719">"<xliff:g id="LEVEL">%1$s</xliff:g> - <xliff:g id="TIME">%2$s</xliff:g> guztiz kargatu arte"</string> - <string name="power_charging_limited" msgid="8202147604844938236">"<xliff:g id="LEVEL">%1$s</xliff:g> - Kargatzeko modu optimizatua"</string> + <!-- no translation found for power_charging_limited (4144004473976005214) --> + <skip /> <string name="power_charging_future_paused" msgid="1809543660923642799">"<xliff:g id="LEVEL">%1$s</xliff:g> ‑ Kargatzen"</string> <string name="power_fast_charging_duration_v2" msgid="3797735998640359490">"<xliff:g id="LEVEL">%1$s</xliff:g> - <xliff:g id="STATUS">%2$s</xliff:g> - Ordu honetan kargatuko da guztiz: <xliff:g id="TIME">%3$s</xliff:g>"</string> <string name="power_charging_duration_v2" msgid="2938998284074003248">"<xliff:g id="LEVEL">%1$s</xliff:g> - Ordu honetan kargatuko da guztiz: <xliff:g id="TIME">%2$s</xliff:g>"</string> diff --git a/packages/SettingsLib/res/values-fa/strings.xml b/packages/SettingsLib/res/values-fa/strings.xml index 5e4d29a959b2..f7279b10c49f 100644 --- a/packages/SettingsLib/res/values-fa/strings.xml +++ b/packages/SettingsLib/res/values-fa/strings.xml @@ -430,8 +430,7 @@ <string name="force_allow_on_external_summary" msgid="8525425782530728238">"بدون توجه به مقادیر آشکار، هر برنامهای را برای نوشتن در حافظه خارجی واجد شرایط میکند"</string> <string name="force_resizable_activities" msgid="7143612144399959606">"اجبار فعالیتها به قابل تغییر اندازه بودن"</string> <string name="force_resizable_activities_summary" msgid="2490382056981583062">"بدون توجه به مقادیر مانیفست، اندازه همه فعالیتها برای حالت چند پنجرهای میتواند تغییر کند."</string> - <string name="enable_freeform_support" msgid="8409932201445109106">"فعال کردن پنجرههای با قالب آزاد (قدیمی)"</string> - <string name="enable_freeform_support_summary" msgid="2242481082356957934">"فعال کردن پشتیبانی از پنجرههای با قالب آزاد قدیمی آزمایشی."</string> + <string name="enable_freeform_support" msgid="7599125687603914253">"فعال کردن پنجرههای آزاد"</string> <string name="local_backup_password_title" msgid="4631017948933578709">"گذرواژه پشتیبانگیری محلی"</string> <string name="local_backup_password_summary_none" msgid="7646898032616361714">"پشتیبانگیری کامل رایانه درحال حاضر محافظت نمیشود"</string> <string name="local_backup_password_summary_change" msgid="1707357670383995567">"برای تغییر یا حذف گذرواژه برای نسخههای پشتیبان کامل رایانهای تکضرب بزنید"</string> @@ -496,7 +495,8 @@ <string name="power_charging" msgid="6727132649743436802">"<xliff:g id="LEVEL">%1$s</xliff:g> - <xliff:g id="STATE">%2$s</xliff:g>"</string> <string name="power_remaining_charging_duration_only" msgid="8085099012811384899">"<xliff:g id="TIME">%1$s</xliff:g> تا شارژ کامل باقی مانده است"</string> <string name="power_charging_duration" msgid="6127154952524919719">"<xliff:g id="LEVEL">%1$s</xliff:g> - <xliff:g id="TIME">%2$s</xliff:g> تا شارژ کامل باقی مانده است"</string> - <string name="power_charging_limited" msgid="8202147604844938236">"<xliff:g id="LEVEL">%1$s</xliff:g> - شارژ بهینه شده است"</string> + <!-- no translation found for power_charging_limited (4144004473976005214) --> + <skip /> <string name="power_charging_future_paused" msgid="1809543660923642799">"<xliff:g id="LEVEL">%1$s</xliff:g> - درحال شارژ"</string> <string name="power_fast_charging_duration_v2" msgid="3797735998640359490">"<xliff:g id="LEVEL">%1$s</xliff:g> - <xliff:g id="STATUS">%2$s</xliff:g> - تا <xliff:g id="TIME">%3$s</xliff:g> کامل میشود"</string> <string name="power_charging_duration_v2" msgid="2938998284074003248">"<xliff:g id="LEVEL">%1$s</xliff:g> - شارژ تا <xliff:g id="TIME">%2$s</xliff:g> کامل میشود"</string> diff --git a/packages/SettingsLib/res/values-fi/strings.xml b/packages/SettingsLib/res/values-fi/strings.xml index ad0cab36ce17..03f6b0a2d764 100644 --- a/packages/SettingsLib/res/values-fi/strings.xml +++ b/packages/SettingsLib/res/values-fi/strings.xml @@ -430,8 +430,7 @@ <string name="force_allow_on_external_summary" msgid="8525425782530728238">"Mahdollistaa sovelluksen tietojen tallentamisen ulkoiseen tallennustilaan luetteloarvoista riippumatta"</string> <string name="force_resizable_activities" msgid="7143612144399959606">"Pakota kaikki toiminnot hyväksymään koon muutos"</string> <string name="force_resizable_activities_summary" msgid="2490382056981583062">"Pakota kaikki toiminnot hyväksymään koon muuttaminen usean ikkunan tilassa luettelon arvoista riippumatta"</string> - <string name="enable_freeform_support" msgid="8409932201445109106">"Ota vapaamuotoiset ikkunat käyttöön (vanha)"</string> - <string name="enable_freeform_support_summary" msgid="2242481082356957934">"Ota kokeellinen vapaamuotoisten ikkunoiden tuki käyttöön (vanha)."</string> + <string name="enable_freeform_support" msgid="7599125687603914253">"Ota käyttöön vapaamuotoiset ikkunat"</string> <string name="local_backup_password_title" msgid="4631017948933578709">"Varmuuskop. salasana"</string> <string name="local_backup_password_summary_none" msgid="7646898032616361714">"Tietokoneen kaikkien tietojen varmuuskopiointia ei ole tällä hetkellä suojattu"</string> <string name="local_backup_password_summary_change" msgid="1707357670383995567">"Vaihda tai poista tietokoneen kaikkien tietojen varmuuskopioinnin salasana koskettamalla."</string> @@ -496,7 +495,8 @@ <string name="power_charging" msgid="6727132649743436802">"<xliff:g id="LEVEL">%1$s</xliff:g> – <xliff:g id="STATE">%2$s</xliff:g>"</string> <string name="power_remaining_charging_duration_only" msgid="8085099012811384899">"<xliff:g id="TIME">%1$s</xliff:g> kunnes täynnä"</string> <string name="power_charging_duration" msgid="6127154952524919719">"<xliff:g id="LEVEL">%1$s</xliff:g> – <xliff:g id="TIME">%2$s</xliff:g> kunnes täynnä"</string> - <string name="power_charging_limited" msgid="8202147604844938236">"<xliff:g id="LEVEL">%1$s</xliff:g> – Lataus optimoitu"</string> + <!-- no translation found for power_charging_limited (4144004473976005214) --> + <skip /> <string name="power_charging_future_paused" msgid="1809543660923642799">"<xliff:g id="LEVEL">%1$s</xliff:g> – Ladataan"</string> <string name="power_fast_charging_duration_v2" msgid="3797735998640359490">"<xliff:g id="LEVEL">%1$s</xliff:g> – <xliff:g id="STATUS">%2$s</xliff:g> – Täynnä klo <xliff:g id="TIME">%3$s</xliff:g> mennessä"</string> <string name="power_charging_duration_v2" msgid="2938998284074003248">"<xliff:g id="LEVEL">%1$s</xliff:g> – Ladattu täyteen klo <xliff:g id="TIME">%2$s</xliff:g> mennessä"</string> diff --git a/packages/SettingsLib/res/values-fr-rCA/strings.xml b/packages/SettingsLib/res/values-fr-rCA/strings.xml index e46d20af1993..04bcb6cd928c 100644 --- a/packages/SettingsLib/res/values-fr-rCA/strings.xml +++ b/packages/SettingsLib/res/values-fr-rCA/strings.xml @@ -430,8 +430,7 @@ <string name="force_allow_on_external_summary" msgid="8525425782530728238">"Rend possible l\'enregistrement de toute appli sur un espace de stockage externe, indépendamment des valeurs du fichier manifeste"</string> <string name="force_resizable_activities" msgid="7143612144399959606">"Forcer les activités à être redimensionnables"</string> <string name="force_resizable_activities_summary" msgid="2490382056981583062">"Permet de redimensionner toutes les activités pour le mode multi-fenêtre, indépendamment des valeurs du fichier manifeste."</string> - <string name="enable_freeform_support" msgid="8409932201445109106">"Activer fenêtres de forme libre (patrimoniales)"</string> - <string name="enable_freeform_support_summary" msgid="2242481082356957934">"Activer la prise en charge des fenêtres de forme libre patrimoniales expérimentales."</string> + <string name="enable_freeform_support" msgid="7599125687603914253">"Activer les fenêtres de forme libre"</string> <string name="local_backup_password_title" msgid="4631017948933578709">"Mot de passe sauvegarde PC"</string> <string name="local_backup_password_summary_none" msgid="7646898032616361714">"Les sauvegardes complètes sur PC ne sont pas protégées actuellement"</string> <string name="local_backup_password_summary_change" msgid="1707357670383995567">"Touchez pour modifier ou supprimer le mot de passe utilisé pour les sauvegardes complètes sur ordinateur."</string> @@ -496,7 +495,8 @@ <string name="power_charging" msgid="6727132649743436802">"<xliff:g id="LEVEL">%1$s</xliff:g> - <xliff:g id="STATE">%2$s</xliff:g>"</string> <string name="power_remaining_charging_duration_only" msgid="8085099012811384899">"<xliff:g id="TIME">%1$s</xliff:g> jusqu\'à la recharge complète"</string> <string name="power_charging_duration" msgid="6127154952524919719">"<xliff:g id="LEVEL">%1$s</xliff:g> (<xliff:g id="TIME">%2$s</xliff:g> jusqu\'à la recharge complète)"</string> - <string name="power_charging_limited" msgid="8202147604844938236">"<xliff:g id="LEVEL">%1$s</xliff:g> - Recharge optimisée"</string> + <!-- no translation found for power_charging_limited (4144004473976005214) --> + <skip /> <string name="power_charging_future_paused" msgid="1809543660923642799">"<xliff:g id="LEVEL">%1$s</xliff:g> – Recharge en cours…"</string> <string name="power_fast_charging_duration_v2" msgid="3797735998640359490">"<xliff:g id="LEVEL">%1$s</xliff:g> – <xliff:g id="STATUS">%2$s</xliff:g> – Recharge complète d\'ici <xliff:g id="TIME">%3$s</xliff:g>"</string> <string name="power_charging_duration_v2" msgid="2938998284074003248">"<xliff:g id="LEVEL">%1$s</xliff:g> – Recharge complète d\'ici <xliff:g id="TIME">%2$s</xliff:g>"</string> diff --git a/packages/SettingsLib/res/values-fr/strings.xml b/packages/SettingsLib/res/values-fr/strings.xml index c60e8ce1f6c5..455fd23bb077 100644 --- a/packages/SettingsLib/res/values-fr/strings.xml +++ b/packages/SettingsLib/res/values-fr/strings.xml @@ -430,8 +430,7 @@ <string name="force_allow_on_external_summary" msgid="8525425782530728238">"Autoriser l\'enregistrement de toute application sur un espace de stockage externe, indépendamment des valeurs du fichier manifeste"</string> <string name="force_resizable_activities" msgid="7143612144399959606">"Forcer le redimensionnement des activités"</string> <string name="force_resizable_activities_summary" msgid="2490382056981583062">"Rendre toutes les activités redimensionnables pour le mode multifenêtre, indépendamment des valeurs du fichier manifeste"</string> - <string name="enable_freeform_support" msgid="8409932201445109106">"Activer les anciennes fenêtres de forme libre"</string> - <string name="enable_freeform_support_summary" msgid="2242481082356957934">"Permet d\'activer la compatibilité avec les anciennes fenêtres de forme libre expérimentales."</string> + <string name="enable_freeform_support" msgid="7599125687603914253">"Activer les fenêtres de forme libre"</string> <string name="local_backup_password_title" msgid="4631017948933578709">"Mot de passe de sauvegarde ordi"</string> <string name="local_backup_password_summary_none" msgid="7646898032616361714">"Les sauvegardes complètes sur ordi ne sont actuellement pas protégées"</string> <string name="local_backup_password_summary_change" msgid="1707357670383995567">"Appuyez pour modifier ou supprimer le mot de passe des sauvegardes complètes sur ordi."</string> @@ -496,7 +495,8 @@ <string name="power_charging" msgid="6727132649743436802">"<xliff:g id="LEVEL">%1$s</xliff:g> – <xliff:g id="STATE">%2$s</xliff:g>"</string> <string name="power_remaining_charging_duration_only" msgid="8085099012811384899">"Chargée à 100 %% dans <xliff:g id="TIME">%1$s</xliff:g>"</string> <string name="power_charging_duration" msgid="6127154952524919719">"<xliff:g id="LEVEL">%1$s</xliff:g> - chargée à 100 %% dans <xliff:g id="TIME">%2$s</xliff:g>"</string> - <string name="power_charging_limited" msgid="8202147604844938236">"<xliff:g id="LEVEL">%1$s</xliff:g> - Recharge optimisée"</string> + <!-- no translation found for power_charging_limited (4144004473976005214) --> + <skip /> <string name="power_charging_future_paused" msgid="1809543660923642799">"<xliff:g id="LEVEL">%1$s</xliff:g> - En charge"</string> <string name="power_fast_charging_duration_v2" msgid="3797735998640359490">"<xliff:g id="LEVEL">%1$s</xliff:g> - <xliff:g id="STATUS">%2$s</xliff:g> - Complètement chargé d\'ici <xliff:g id="TIME">%3$s</xliff:g>"</string> <string name="power_charging_duration_v2" msgid="2938998284074003248">"<xliff:g id="LEVEL">%1$s</xliff:g> - Complètement chargé dans <xliff:g id="TIME">%2$s</xliff:g>"</string> diff --git a/packages/SettingsLib/res/values-gl/strings.xml b/packages/SettingsLib/res/values-gl/strings.xml index 9f58bd44e883..7127ca8cf25a 100644 --- a/packages/SettingsLib/res/values-gl/strings.xml +++ b/packages/SettingsLib/res/values-gl/strings.xml @@ -430,8 +430,7 @@ <string name="force_allow_on_external_summary" msgid="8525425782530728238">"Permite que calquera aplicación compatible se poida escribir nun almacenamento externo, independentemente dos valores do manifesto"</string> <string name="force_resizable_activities" msgid="7143612144399959606">"Forzar o axuste do tamaño das actividades"</string> <string name="force_resizable_activities_summary" msgid="2490382056981583062">"Permite axustar o tamaño de todas as actividades para o modo multiventá, independentemente dos valores do manifesto"</string> - <string name="enable_freeform_support" msgid="8409932201445109106">"Activar ventás de forma libre (antigas)"</string> - <string name="enable_freeform_support_summary" msgid="2242481082356957934">"Activa a compatibilidade coas ventás de forma libre experimentais antigas."</string> + <string name="enable_freeform_support" msgid="7599125687603914253">"Activar ventás de forma libre"</string> <string name="local_backup_password_title" msgid="4631017948933578709">"Contrasinal para copias"</string> <string name="local_backup_password_summary_none" msgid="7646898032616361714">"As copias de seguranza de ordenador completas non están protexidas"</string> <string name="local_backup_password_summary_change" msgid="1707357670383995567">"Toca para cambiar ou quitar o contrasinal para as copias de seguranza completas de ordenador"</string> @@ -496,7 +495,8 @@ <string name="power_charging" msgid="6727132649743436802">"<xliff:g id="LEVEL">%1$s</xliff:g> - <xliff:g id="STATE">%2$s</xliff:g>"</string> <string name="power_remaining_charging_duration_only" msgid="8085099012811384899">"<xliff:g id="TIME">%1$s</xliff:g> para completar a carga"</string> <string name="power_charging_duration" msgid="6127154952524919719">"<xliff:g id="LEVEL">%1$s</xliff:g> (<xliff:g id="TIME">%2$s</xliff:g> para completar a carga)"</string> - <string name="power_charging_limited" msgid="8202147604844938236">"<xliff:g id="LEVEL">%1$s</xliff:g> (carga optimizada)"</string> + <!-- no translation found for power_charging_limited (4144004473976005214) --> + <skip /> <string name="power_charging_future_paused" msgid="1809543660923642799">"<xliff:g id="LEVEL">%1$s</xliff:g> (cargando)"</string> <string name="power_fast_charging_duration_v2" msgid="3797735998640359490">"<xliff:g id="LEVEL">%1$s</xliff:g> - <xliff:g id="STATUS">%2$s</xliff:g> - Completarase á/s <xliff:g id="TIME">%3$s</xliff:g>"</string> <string name="power_charging_duration_v2" msgid="2938998284074003248">"<xliff:g id="LEVEL">%1$s</xliff:g> - Carga completa á/s <xliff:g id="TIME">%2$s</xliff:g>"</string> diff --git a/packages/SettingsLib/res/values-gu/strings.xml b/packages/SettingsLib/res/values-gu/strings.xml index b44f0c72041c..f89e148600f7 100644 --- a/packages/SettingsLib/res/values-gu/strings.xml +++ b/packages/SettingsLib/res/values-gu/strings.xml @@ -430,8 +430,7 @@ <string name="force_allow_on_external_summary" msgid="8525425782530728238">"મેનિફેસ્ટ મૂલ્યોને ધ્યાનમાં લીધા સિવાય, કોઈપણ ઍપને બાહ્ય સ્ટોરેજ પર લખાવા માટે લાયક બનાવે છે"</string> <string name="force_resizable_activities" msgid="7143612144399959606">"પ્રવૃત્તિઓને ફરીથી કદ યોગ્ય થવા માટે ફરજ પાડો"</string> <string name="force_resizable_activities_summary" msgid="2490382056981583062">"મૅનિફેસ્ટ મૂલ્યોને ધ્યાનમાં લીધા સિવાય, તમામ પ્રવૃત્તિઓને મલ્ટી-વિન્ડો માટે ફરીથી કદ બદલી શકે તેવી બનાવો."</string> - <string name="enable_freeform_support" msgid="8409932201445109106">"ફ્રીફોર્મ વિન્ડો ચાલુ કરો (જૂની)"</string> - <string name="enable_freeform_support_summary" msgid="2242481082356957934">"પ્રાયોગિક જૂની ફ્રીફોર્મ વિન્ડો માટે સપોર્ટ મેળવવાની સુવિધા ચાલુ કરો."</string> + <string name="enable_freeform_support" msgid="7599125687603914253">"ફ્રીફોર્મ વિન્ડો ચાલુ કરો"</string> <string name="local_backup_password_title" msgid="4631017948933578709">"ડેસ્કટૉપ બૅકઅપ પાસવર્ડ"</string> <string name="local_backup_password_summary_none" msgid="7646898032616361714">"ડેસ્કટૉપ સંપૂર્ણ બૅકઅપ હાલમાં સુરક્ષિત નથી"</string> <string name="local_backup_password_summary_change" msgid="1707357670383995567">"ડેસ્કટૉપ સંપૂર્ણ બેકઅપ્સ માટેનો પાસવર્ડ બદલવા અથવા દૂર કરવા માટે ટૅચ કરો"</string> @@ -496,7 +495,8 @@ <string name="power_charging" msgid="6727132649743436802">"<xliff:g id="LEVEL">%1$s</xliff:g> - <xliff:g id="STATE">%2$s</xliff:g>"</string> <string name="power_remaining_charging_duration_only" msgid="8085099012811384899">"પૂર્ણ ચાર્જ થવામાં <xliff:g id="TIME">%1$s</xliff:g> બાકી છે"</string> <string name="power_charging_duration" msgid="6127154952524919719">"<xliff:g id="LEVEL">%1$s</xliff:g> - પૂર્ણ ચાર્જ થવામાં <xliff:g id="TIME">%2$s</xliff:g> બાકી છે"</string> - <string name="power_charging_limited" msgid="8202147604844938236">"<xliff:g id="LEVEL">%1$s</xliff:g> - ચાર્જિંગ ઑપ્ટિમાઇઝ કરવામાં આવ્યું છે"</string> + <!-- no translation found for power_charging_limited (4144004473976005214) --> + <skip /> <string name="power_charging_future_paused" msgid="1809543660923642799">"<xliff:g id="LEVEL">%1$s</xliff:g> - ચાર્જિંગ"</string> <string name="power_fast_charging_duration_v2" msgid="3797735998640359490">"<xliff:g id="LEVEL">%1$s</xliff:g> - <xliff:g id="STATUS">%2$s</xliff:g> - <xliff:g id="TIME">%3$s</xliff:g> સુધીમાં સંપૂર્ણ ચાર્જ થશે"</string> <string name="power_charging_duration_v2" msgid="2938998284074003248">"<xliff:g id="LEVEL">%1$s</xliff:g> - <xliff:g id="TIME">%2$s</xliff:g> સુધીમાં સંપૂર્ણ ચાર્જ થશે"</string> diff --git a/packages/SettingsLib/res/values-hi/strings.xml b/packages/SettingsLib/res/values-hi/strings.xml index 246f66e8dcc3..adf8b5fa2606 100644 --- a/packages/SettingsLib/res/values-hi/strings.xml +++ b/packages/SettingsLib/res/values-hi/strings.xml @@ -430,8 +430,7 @@ <string name="force_allow_on_external_summary" msgid="8525425782530728238">"इससे कोई भी ऐप्लिकेशन बाहरी स्टोरेज में रखने लायक बन जाता है, चाहे उसकी मेनिफ़ेस्ट वैल्यू कुछ भी हो"</string> <string name="force_resizable_activities" msgid="7143612144399959606">"विंडो के हिसाब से गतिविधियों का साइज़ बदल दें"</string> <string name="force_resizable_activities_summary" msgid="2490382056981583062">"सभी गतिविधियों को मल्टी-विंडो (एक से ज़्यादा ऐप्लिकेशन, एक साथ) के लिए साइज़ बदलने लायक बनाएं, चाहे उनकी मेनिफ़ेस्ट वैल्यू कुछ भी हो."</string> - <string name="enable_freeform_support" msgid="8409932201445109106">"फ़्रीफ़ॉर्म विंडो वाला लेगसी मोड चालू करें"</string> - <string name="enable_freeform_support_summary" msgid="2242481082356957934">"एक्सपेरिमेंट के तौर पर उपलब्ध फ़्रीफ़ॉर्म विंडो वाला लेगसी मोड चालू करें."</string> + <string name="enable_freeform_support" msgid="7599125687603914253">"फ़्रीफ़ॉर्म विंडो (एक साथ कई विंडो दिखाना) चालू करें"</string> <string name="local_backup_password_title" msgid="4631017948933578709">"डेस्कटॉप बैकअप पासवर्ड"</string> <string name="local_backup_password_summary_none" msgid="7646898032616361714">"डेस्कटॉप का पूरा बैकअप फ़िलहाल सुरक्षित नहीं है"</string> <string name="local_backup_password_summary_change" msgid="1707357670383995567">"डेस्कटॉप के पूरे बैक अप का पासवर्ड बदलने या हटाने के लिए टैप करें"</string> @@ -496,7 +495,8 @@ <string name="power_charging" msgid="6727132649743436802">"<xliff:g id="LEVEL">%1$s</xliff:g> - <xliff:g id="STATE">%2$s</xliff:g>"</string> <string name="power_remaining_charging_duration_only" msgid="8085099012811384899">"<xliff:g id="TIME">%1$s</xliff:g> में बैटरी पूरी चार्ज हो जाएगी"</string> <string name="power_charging_duration" msgid="6127154952524919719">"<xliff:g id="LEVEL">%1$s</xliff:g> - <xliff:g id="TIME">%2$s</xliff:g> में बैटरी पूरी चार्ज हो जाएगी"</string> - <string name="power_charging_limited" msgid="8202147604844938236">"<xliff:g id="LEVEL">%1$s</xliff:g> - चार्जिंग को ऑप्टिमाइज़ किया गया"</string> + <!-- no translation found for power_charging_limited (4144004473976005214) --> + <skip /> <string name="power_charging_future_paused" msgid="1809543660923642799">"<xliff:g id="LEVEL">%1$s</xliff:g> - चार्ज हो रही है"</string> <string name="power_fast_charging_duration_v2" msgid="3797735998640359490">"<xliff:g id="LEVEL">%1$s</xliff:g> - <xliff:g id="STATUS">%2$s</xliff:g> - बैटरी <xliff:g id="TIME">%3$s</xliff:g> में पूरी चार्ज हो जाएगी"</string> <string name="power_charging_duration_v2" msgid="2938998284074003248">"<xliff:g id="LEVEL">%1$s</xliff:g> - बैटरी <xliff:g id="TIME">%2$s</xliff:g> में पूरी चार्ज हो जाएगी"</string> diff --git a/packages/SettingsLib/res/values-hr/strings.xml b/packages/SettingsLib/res/values-hr/strings.xml index f4bb6ea36e54..3c20bf478fee 100644 --- a/packages/SettingsLib/res/values-hr/strings.xml +++ b/packages/SettingsLib/res/values-hr/strings.xml @@ -430,8 +430,7 @@ <string name="force_allow_on_external_summary" msgid="8525425782530728238">"Aplikacije se mogu zapisivati u vanjsku pohranu neovisno o vrijednostima manifesta"</string> <string name="force_resizable_activities" msgid="7143612144399959606">"Nametni mogućnost promjene veličine za aktivnosti"</string> <string name="force_resizable_activities_summary" msgid="2490382056981583062">"Omogući mijenjanje veličine svih aktivnosti za više prozora, neovisno o vrijednostima manifesta."</string> - <string name="enable_freeform_support" msgid="8409932201445109106">"Omogući prozore slobodnog oblika (naslijeđeno)"</string> - <string name="enable_freeform_support_summary" msgid="2242481082356957934">"Omogući podršku za eksperimentalne naslijeđene prozore slobodnog oblika."</string> + <string name="enable_freeform_support" msgid="7599125687603914253">"Omogući prozore slobodnog oblika"</string> <string name="local_backup_password_title" msgid="4631017948933578709">"Zaporka sigurnosne kopije"</string> <string name="local_backup_password_summary_none" msgid="7646898032616361714">"Potpune sigurnosne kopije na stolnom računalu trenutačno nisu zaštićene"</string> <string name="local_backup_password_summary_change" msgid="1707357670383995567">"Dodirnite da biste promijenili ili uklonili zaporku za potpune sigurnosne kopije na računalu"</string> @@ -496,7 +495,8 @@ <string name="power_charging" msgid="6727132649743436802">"<xliff:g id="LEVEL">%1$s</xliff:g> – <xliff:g id="STATE">%2$s</xliff:g>"</string> <string name="power_remaining_charging_duration_only" msgid="8085099012811384899">"<xliff:g id="TIME">%1$s</xliff:g> do napunjenosti"</string> <string name="power_charging_duration" msgid="6127154952524919719">"<xliff:g id="LEVEL">%1$s</xliff:g> – <xliff:g id="TIME">%2$s</xliff:g> do napunjenosti"</string> - <string name="power_charging_limited" msgid="8202147604844938236">"<xliff:g id="LEVEL">%1$s</xliff:g> – punjenje se optimizira"</string> + <!-- no translation found for power_charging_limited (4144004473976005214) --> + <skip /> <string name="power_charging_future_paused" msgid="1809543660923642799">"<xliff:g id="LEVEL">%1$s</xliff:g> – punjenje"</string> <string name="power_fast_charging_duration_v2" msgid="3797735998640359490">"<xliff:g id="LEVEL">%1$s</xliff:g> – <xliff:g id="STATUS">%2$s</xliff:g> – bit će pun do <xliff:g id="TIME">%3$s</xliff:g>"</string> <string name="power_charging_duration_v2" msgid="2938998284074003248">"<xliff:g id="LEVEL">%1$s</xliff:g> – potpuno napunjeno do <xliff:g id="TIME">%2$s</xliff:g>"</string> diff --git a/packages/SettingsLib/res/values-hu/strings.xml b/packages/SettingsLib/res/values-hu/strings.xml index db739d56c8a3..fd938b93cf4a 100644 --- a/packages/SettingsLib/res/values-hu/strings.xml +++ b/packages/SettingsLib/res/values-hu/strings.xml @@ -430,8 +430,7 @@ <string name="force_allow_on_external_summary" msgid="8525425782530728238">"Lehetővé teszi bármely alkalmazás külső tárhelyre való írását a jegyzékértékektől függetlenül"</string> <string name="force_resizable_activities" msgid="7143612144399959606">"Tevékenységek átméretezésének kényszerítése"</string> <string name="force_resizable_activities_summary" msgid="2490382056981583062">"Legyen az összes tevékenység átméretezhető a többablakos megjelenítés érdekében a jegyzékértékektől függetlenül."</string> - <string name="enable_freeform_support" msgid="8409932201445109106">"Szabad formájú ablakok engedélyezése (régi)"</string> - <string name="enable_freeform_support_summary" msgid="2242481082356957934">"Kísérleti, régi szabad formájú ablakok támogatásának engedélyezése."</string> + <string name="enable_freeform_support" msgid="7599125687603914253">"Szabad formájú ablakok engedélyezése"</string> <string name="local_backup_password_title" msgid="4631017948933578709">"Asztali mentés jelszava"</string> <string name="local_backup_password_summary_none" msgid="7646898032616361714">"Az asztali teljes biztonsági mentések jelenleg nem védettek."</string> <string name="local_backup_password_summary_change" msgid="1707357670383995567">"Koppintson ide az asztali teljes mentések jelszavának módosításához vagy eltávolításához"</string> @@ -496,7 +495,8 @@ <string name="power_charging" msgid="6727132649743436802">"<xliff:g id="LEVEL">%1$s</xliff:g> – <xliff:g id="STATE">%2$s</xliff:g>"</string> <string name="power_remaining_charging_duration_only" msgid="8085099012811384899">"<xliff:g id="TIME">%1$s</xliff:g> a teljes töltöttségig"</string> <string name="power_charging_duration" msgid="6127154952524919719">"<xliff:g id="LEVEL">%1$s</xliff:g> – <xliff:g id="TIME">%2$s</xliff:g> a teljes töltöttségig"</string> - <string name="power_charging_limited" msgid="8202147604844938236">"<xliff:g id="LEVEL">%1$s</xliff:g> – Optimalizált töltés"</string> + <!-- no translation found for power_charging_limited (4144004473976005214) --> + <skip /> <string name="power_charging_future_paused" msgid="1809543660923642799">"<xliff:g id="LEVEL">%1$s</xliff:g> – Töltés…"</string> <string name="power_fast_charging_duration_v2" msgid="3797735998640359490">"<xliff:g id="LEVEL">%1$s</xliff:g> – <xliff:g id="STATUS">%2$s</xliff:g> – Teljes feltöltés eddig: <xliff:g id="TIME">%3$s</xliff:g>"</string> <string name="power_charging_duration_v2" msgid="2938998284074003248">"<xliff:g id="LEVEL">%1$s</xliff:g> – Teljes feltöltés eddig: <xliff:g id="TIME">%2$s</xliff:g>"</string> diff --git a/packages/SettingsLib/res/values-hy/strings.xml b/packages/SettingsLib/res/values-hy/strings.xml index 717313fbb2bf..389aad280230 100644 --- a/packages/SettingsLib/res/values-hy/strings.xml +++ b/packages/SettingsLib/res/values-hy/strings.xml @@ -430,8 +430,7 @@ <string name="force_allow_on_external_summary" msgid="8525425782530728238">"Թույլ է տալիս ցանկացած հավելված պահել արտաքին սարքում՝ մանիֆեստի արժեքներից անկախ"</string> <string name="force_resizable_activities" msgid="7143612144399959606">"Չափերի փոփոխում բազմապատուհան ռեժիմում"</string> <string name="force_resizable_activities_summary" msgid="2490382056981583062">"Բոլոր ակտիվությունների չափերը բազմապատուհան ռեժիմի համար դարձնել փոփոխելի՝ մանիֆեստի արժեքներից անկախ:"</string> - <string name="enable_freeform_support" msgid="8409932201445109106">"Միացնել կամայական ձևի պատուհանները (հնացած)"</string> - <string name="enable_freeform_support_summary" msgid="2242481082356957934">"Միացնել կամայական ձևի պատուհանների ստեղծման հնացած փորձնական գործառույթի աջակցումը:"</string> + <string name="enable_freeform_support" msgid="7599125687603914253">"Ակտիվացնել կամայական ձևի պատուհանները"</string> <string name="local_backup_password_title" msgid="4631017948933578709">"Աշխատասեղանի պահուստավորման գաղտնաբառ"</string> <string name="local_backup_password_summary_none" msgid="7646898032616361714">"Աշխատասեղանի ամբողջական պահուստավորումները այժմ պաշտպանված չեն"</string> <string name="local_backup_password_summary_change" msgid="1707357670383995567">"Հպեք՝ աշխատասեղանի ամբողջական պահուստավորման գաղտնաբառը փոխելու կամ հեռացնելու համար"</string> @@ -496,7 +495,8 @@ <string name="power_charging" msgid="6727132649743436802">"<xliff:g id="LEVEL">%1$s</xliff:g> - <xliff:g id="STATE">%2$s</xliff:g>"</string> <string name="power_remaining_charging_duration_only" msgid="8085099012811384899">"<xliff:g id="TIME">%1$s</xliff:g> մինչև լրիվ լիցքավորումը"</string> <string name="power_charging_duration" msgid="6127154952524919719">"<xliff:g id="LEVEL">%1$s</xliff:g> – <xliff:g id="TIME">%2$s</xliff:g> մինչև լրիվ լիցքավորումը"</string> - <string name="power_charging_limited" msgid="8202147604844938236">"<xliff:g id="LEVEL">%1$s</xliff:g> – Լիցքավորումն օպտիմալացված է"</string> + <!-- no translation found for power_charging_limited (4144004473976005214) --> + <skip /> <string name="power_charging_future_paused" msgid="1809543660923642799">"<xliff:g id="LEVEL">%1$s</xliff:g> — Լիցքավորում"</string> <string name="power_fast_charging_duration_v2" msgid="3797735998640359490">"<xliff:g id="LEVEL">%1$s</xliff:g> – <xliff:g id="STATUS">%2$s</xliff:g> – Ամբողջովին կլիցքավորվի մինչև <xliff:g id="TIME">%3$s</xliff:g>"</string> <string name="power_charging_duration_v2" msgid="2938998284074003248">"<xliff:g id="LEVEL">%1$s</xliff:g> – Ամբողջովին կլիցքավորվի մինչև <xliff:g id="TIME">%2$s</xliff:g>"</string> diff --git a/packages/SettingsLib/res/values-in/strings.xml b/packages/SettingsLib/res/values-in/strings.xml index 748d5ed4b239..c6bd3e92d1d4 100644 --- a/packages/SettingsLib/res/values-in/strings.xml +++ b/packages/SettingsLib/res/values-in/strings.xml @@ -430,8 +430,7 @@ <string name="force_allow_on_external_summary" msgid="8525425782530728238">"Membuat semua aplikasi dapat ditulis ke penyimpanan eksternal, terlepas dari nilai manifes"</string> <string name="force_resizable_activities" msgid="7143612144399959606">"Paksa aktivitas agar ukurannya dapat diubah"</string> <string name="force_resizable_activities_summary" msgid="2490382056981583062">"Membuat semua aktivitas dapat diubah ukurannya untuk banyak jendela, terlepas dari nilai manifes."</string> - <string name="enable_freeform_support" msgid="8409932201445109106">"Aktifkan jendela freeform (versi lama)"</string> - <string name="enable_freeform_support_summary" msgid="2242481082356957934">"Aktifkan dukungan untuk jendela freeform eksperimental versi lama."</string> + <string name="enable_freeform_support" msgid="7599125687603914253">"Aktifkan jendela berformat bebas"</string> <string name="local_backup_password_title" msgid="4631017948933578709">"Sandi cadangan desktop"</string> <string name="local_backup_password_summary_none" msgid="7646898032616361714">"Saat ini cadangan desktop penuh tidak dilindungi"</string> <string name="local_backup_password_summary_change" msgid="1707357670383995567">"Ketuk guna mengubah atau menghapus sandi untuk cadangan lengkap desktop"</string> @@ -496,7 +495,8 @@ <string name="power_charging" msgid="6727132649743436802">"<xliff:g id="LEVEL">%1$s</xliff:g> - <xliff:g id="STATE">%2$s</xliff:g>"</string> <string name="power_remaining_charging_duration_only" msgid="8085099012811384899">"<xliff:g id="TIME">%1$s</xliff:g> lagi sampai penuh"</string> <string name="power_charging_duration" msgid="6127154952524919719">"<xliff:g id="LEVEL">%1$s</xliff:g> - <xliff:g id="TIME">%2$s</xliff:g> lagi sampai penuh"</string> - <string name="power_charging_limited" msgid="8202147604844938236">"<xliff:g id="LEVEL">%1$s</xliff:g> - Pengisian daya dioptimalkan"</string> + <!-- no translation found for power_charging_limited (4144004473976005214) --> + <skip /> <string name="power_charging_future_paused" msgid="1809543660923642799">"<xliff:g id="LEVEL">%1$s</xliff:g> - Mengisi daya"</string> <string name="power_fast_charging_duration_v2" msgid="3797735998640359490">"<xliff:g id="LEVEL">%1$s</xliff:g> - <xliff:g id="STATUS">%2$s</xliff:g> - Penuh pukul <xliff:g id="TIME">%3$s</xliff:g>"</string> <string name="power_charging_duration_v2" msgid="2938998284074003248">"<xliff:g id="LEVEL">%1$s</xliff:g> - Baterai terisi penuh dalam <xliff:g id="TIME">%2$s</xliff:g>"</string> diff --git a/packages/SettingsLib/res/values-is/strings.xml b/packages/SettingsLib/res/values-is/strings.xml index 7871cb283bfe..2575af0fbe84 100644 --- a/packages/SettingsLib/res/values-is/strings.xml +++ b/packages/SettingsLib/res/values-is/strings.xml @@ -430,8 +430,7 @@ <string name="force_allow_on_external_summary" msgid="8525425782530728238">"Gerir öll forrit skrifanleg í ytra geymslurými, óháð gildum í upplýsingaskrá"</string> <string name="force_resizable_activities" msgid="7143612144399959606">"Þvinga breytanlega stærð virkni"</string> <string name="force_resizable_activities_summary" msgid="2490382056981583062">"Gera stærð allrar virkni breytanlega svo að hún henti fyrir marga glugga, óháð gildum í upplýsingaskrá."</string> - <string name="enable_freeform_support" msgid="8409932201445109106">"Virkja glugga á frjálsu sniði (eldra)"</string> - <string name="enable_freeform_support_summary" msgid="2242481082356957934">"Virkja stuðning við eldri tilraunaglugga á frjálsu sniði."</string> + <string name="enable_freeform_support" msgid="7599125687603914253">"Virkja glugga með frjálsu sniði"</string> <string name="local_backup_password_title" msgid="4631017948933578709">"Aðgangsorð tölvuafritunar"</string> <string name="local_backup_password_summary_none" msgid="7646898032616361714">"Heildarafritun á tölvu er ekki varin sem stendur."</string> <string name="local_backup_password_summary_change" msgid="1707357670383995567">"Ýttu til að breyta eða fjarlægja aðgangsorðið fyrir heildarafritun á tölvu"</string> @@ -496,7 +495,8 @@ <string name="power_charging" msgid="6727132649743436802">"<xliff:g id="LEVEL">%1$s</xliff:g> – <xliff:g id="STATE">%2$s</xliff:g>"</string> <string name="power_remaining_charging_duration_only" msgid="8085099012811384899">"<xliff:g id="TIME">%1$s</xliff:g> fram að fullri hleðslu"</string> <string name="power_charging_duration" msgid="6127154952524919719">"<xliff:g id="LEVEL">%1$s</xliff:g> - <xliff:g id="TIME">%2$s</xliff:g> fram að fullri hleðslu"</string> - <string name="power_charging_limited" msgid="8202147604844938236">"<xliff:g id="LEVEL">%1$s</xliff:g> – Hleðsla fínstillt"</string> + <!-- no translation found for power_charging_limited (4144004473976005214) --> + <skip /> <string name="power_charging_future_paused" msgid="1809543660923642799">"<xliff:g id="LEVEL">%1$s</xliff:g> ‑ Í hleðslu"</string> <string name="power_fast_charging_duration_v2" msgid="3797735998640359490">"<xliff:g id="LEVEL">%1$s</xliff:g> - <xliff:g id="STATUS">%2$s</xliff:g> - Fullt kl. <xliff:g id="TIME">%3$s</xliff:g>"</string> <string name="power_charging_duration_v2" msgid="2938998284074003248">"<xliff:g id="LEVEL">%1$s</xliff:g> - Fullhlaðið kl. <xliff:g id="TIME">%2$s</xliff:g>"</string> diff --git a/packages/SettingsLib/res/values-it/strings.xml b/packages/SettingsLib/res/values-it/strings.xml index 8ceaba03ea7b..deae4a5b2ad1 100644 --- a/packages/SettingsLib/res/values-it/strings.xml +++ b/packages/SettingsLib/res/values-it/strings.xml @@ -430,8 +430,7 @@ <string name="force_allow_on_external_summary" msgid="8525425782530728238">"Consente l\'installazione di qualsiasi app su memoria esterna, indipendentemente dai valori manifest"</string> <string name="force_resizable_activities" msgid="7143612144399959606">"Imponi formato modificabile alle attività"</string> <string name="force_resizable_activities_summary" msgid="2490382056981583062">"Rendi il formato di tutte le attività modificabile per la modalità multi-finestra, indipendentemente dai valori manifest"</string> - <string name="enable_freeform_support" msgid="8409932201445109106">"Attiva finestre a forma libera (legacy)"</string> - <string name="enable_freeform_support_summary" msgid="2242481082356957934">"Attiva il supporto delle finestre a forma libera sperimentali legacy."</string> + <string name="enable_freeform_support" msgid="7599125687603914253">"Attiva finestre a forma libera"</string> <string name="local_backup_password_title" msgid="4631017948933578709">"Password di backup desktop"</string> <string name="local_backup_password_summary_none" msgid="7646898032616361714">"I backup desktop completi non sono attualmente protetti"</string> <string name="local_backup_password_summary_change" msgid="1707357670383995567">"Tocca per modificare o rimuovere la password per i backup desktop completi"</string> @@ -496,7 +495,8 @@ <string name="power_charging" msgid="6727132649743436802">"<xliff:g id="LEVEL">%1$s</xliff:g> - <xliff:g id="STATE">%2$s</xliff:g>"</string> <string name="power_remaining_charging_duration_only" msgid="8085099012811384899">"<xliff:g id="TIME">%1$s</xliff:g> alla ricarica completa"</string> <string name="power_charging_duration" msgid="6127154952524919719">"<xliff:g id="LEVEL">%1$s</xliff:g> - <xliff:g id="TIME">%2$s</xliff:g> alla ricarica completa"</string> - <string name="power_charging_limited" msgid="8202147604844938236">"<xliff:g id="LEVEL">%1$s</xliff:g> - Ricarica ottimizzata"</string> + <!-- no translation found for power_charging_limited (4144004473976005214) --> + <skip /> <string name="power_charging_future_paused" msgid="1809543660923642799">"<xliff:g id="LEVEL">%1$s</xliff:g> ‑ In carica"</string> <string name="power_fast_charging_duration_v2" msgid="3797735998640359490">"<xliff:g id="LEVEL">%1$s</xliff:g> - <xliff:g id="STATUS">%2$s</xliff:g> - Ricarica completa entro <xliff:g id="TIME">%3$s</xliff:g>"</string> <string name="power_charging_duration_v2" msgid="2938998284074003248">"<xliff:g id="LEVEL">%1$s</xliff:g> - Batteria completamente carica entro <xliff:g id="TIME">%2$s</xliff:g>"</string> diff --git a/packages/SettingsLib/res/values-iw/strings.xml b/packages/SettingsLib/res/values-iw/strings.xml index f7c96842f64b..310b046c46f7 100644 --- a/packages/SettingsLib/res/values-iw/strings.xml +++ b/packages/SettingsLib/res/values-iw/strings.xml @@ -430,8 +430,7 @@ <string name="force_allow_on_external_summary" msgid="8525425782530728238">"מאפשר כתיבה של כל אפליקציה באחסון חיצוני, ללא התחשבות בערכי המניפסט"</string> <string name="force_resizable_activities" msgid="7143612144399959606">"אילוץ יכולת קביעת גודל של הפעילויות"</string> <string name="force_resizable_activities_summary" msgid="2490382056981583062">"מאפשר יכולת קביעת גודל של כל הפעילויות לריבוי חלונות, ללא התחשבות בערכי המניפסט."</string> - <string name="enable_freeform_support" msgid="8409932201445109106">"הפעלת שינוי הגודל והמיקום של החלונות (מדור קודם)"</string> - <string name="enable_freeform_support_summary" msgid="2242481082356957934">"הפעלת תמיכה בתכונה הניסיונית מדור קודם של שינוי הגודל והמיקום של החלונות."</string> + <string name="enable_freeform_support" msgid="7599125687603914253">"הפעלת האפשרות לשנות את הגודל והמיקום של החלונות"</string> <string name="local_backup_password_title" msgid="4631017948933578709">"סיסמת גיבוי שולחן העבודה"</string> <string name="local_backup_password_summary_none" msgid="7646898032616361714">"גיבויים מלאים בשולחן העבודה אינם מוגנים כעת"</string> <string name="local_backup_password_summary_change" msgid="1707357670383995567">"יש להקיש כדי לשנות או להסיר את הסיסמה לגיבויים מלאים בשולחן העבודה"</string> @@ -496,7 +495,8 @@ <string name="power_charging" msgid="6727132649743436802">"<xliff:g id="LEVEL">%1$s</xliff:g> – <xliff:g id="STATE">%2$s</xliff:g>"</string> <string name="power_remaining_charging_duration_only" msgid="8085099012811384899">"הזמן הנותר לטעינה מלאה: <xliff:g id="TIME">%1$s</xliff:g>"</string> <string name="power_charging_duration" msgid="6127154952524919719">"<xliff:g id="LEVEL">%1$s</xliff:g> – הזמן הנותר לטעינה מלאה: <xliff:g id="TIME">%2$s</xliff:g>"</string> - <string name="power_charging_limited" msgid="8202147604844938236">"<xliff:g id="LEVEL">%1$s</xliff:g> – הטעינה עברה אופטימיזציה"</string> + <!-- no translation found for power_charging_limited (4144004473976005214) --> + <skip /> <string name="power_charging_future_paused" msgid="1809543660923642799">"<xliff:g id="LEVEL">%1$s</xliff:g> – בטעינה"</string> <string name="power_fast_charging_duration_v2" msgid="3797735998640359490">"<xliff:g id="LEVEL">%1$s</xliff:g> – <xliff:g id="STATUS">%2$s</xliff:g> – טעינה מלאה עד <xliff:g id="TIME">%3$s</xliff:g>"</string> <string name="power_charging_duration_v2" msgid="2938998284074003248">"<xliff:g id="LEVEL">%1$s</xliff:g> – טעינה מלאה עד <xliff:g id="TIME">%2$s</xliff:g>"</string> diff --git a/packages/SettingsLib/res/values-ja/strings.xml b/packages/SettingsLib/res/values-ja/strings.xml index cafa95d3c66b..4dc0580505f1 100644 --- a/packages/SettingsLib/res/values-ja/strings.xml +++ b/packages/SettingsLib/res/values-ja/strings.xml @@ -430,8 +430,7 @@ <string name="force_allow_on_external_summary" msgid="8525425782530728238">"マニフェストの値に関係なく、すべてのアプリを外部ストレージに書き込めるようになります"</string> <string name="force_resizable_activities" msgid="7143612144399959606">"アクティビティをサイズ変更可能にする"</string> <string name="force_resizable_activities_summary" msgid="2490382056981583062">"マニフェストの値に関係なく、マルチウィンドウですべてのアクティビティのサイズを変更できるようにします。"</string> - <string name="enable_freeform_support" msgid="8409932201445109106">"フリーフォーム ウィンドウを有効にする(従来版)"</string> - <string name="enable_freeform_support_summary" msgid="2242481082356957934">"従来の試験運用版のフリーフォーム ウィンドウのサポートを有効にします。"</string> + <string name="enable_freeform_support" msgid="7599125687603914253">"フリーフォーム ウィンドウを有効にする"</string> <string name="local_backup_password_title" msgid="4631017948933578709">"PC バックアップ パスワード"</string> <string name="local_backup_password_summary_none" msgid="7646898032616361714">"デスクトップのフルバックアップは現在保護されていません"</string> <string name="local_backup_password_summary_change" msgid="1707357670383995567">"デスクトップのフルバックアップ用のパスワードを変更または削除する場合にタップします"</string> @@ -496,7 +495,8 @@ <string name="power_charging" msgid="6727132649743436802">"<xliff:g id="LEVEL">%1$s</xliff:g> - <xliff:g id="STATE">%2$s</xliff:g>"</string> <string name="power_remaining_charging_duration_only" msgid="8085099012811384899">"完了まであと <xliff:g id="TIME">%1$s</xliff:g>"</string> <string name="power_charging_duration" msgid="6127154952524919719">"<xliff:g id="LEVEL">%1$s</xliff:g> - 完了まであと <xliff:g id="TIME">%2$s</xliff:g>"</string> - <string name="power_charging_limited" msgid="8202147604844938236">"<xliff:g id="LEVEL">%1$s</xliff:g> - 充電が最適化されています"</string> + <!-- no translation found for power_charging_limited (4144004473976005214) --> + <skip /> <string name="power_charging_future_paused" msgid="1809543660923642799">"<xliff:g id="LEVEL">%1$s</xliff:g> - 充電中"</string> <string name="power_fast_charging_duration_v2" msgid="3797735998640359490">"<xliff:g id="LEVEL">%1$s</xliff:g> - <xliff:g id="STATUS">%2$s</xliff:g> - <xliff:g id="TIME">%3$s</xliff:g>までに完了"</string> <string name="power_charging_duration_v2" msgid="2938998284074003248">"<xliff:g id="LEVEL">%1$s</xliff:g> - <xliff:g id="TIME">%2$s</xliff:g>までに充電完了"</string> diff --git a/packages/SettingsLib/res/values-ka/strings.xml b/packages/SettingsLib/res/values-ka/strings.xml index 10a660bdc492..a19684413417 100644 --- a/packages/SettingsLib/res/values-ka/strings.xml +++ b/packages/SettingsLib/res/values-ka/strings.xml @@ -434,8 +434,7 @@ <string name="force_allow_on_external_summary" msgid="8525425782530728238">"აპები ჩაიწერება გარე მეხსიერებაზე აღწერის ფაილების მნიშვნელობების მიუხედავად"</string> <string name="force_resizable_activities" msgid="7143612144399959606">"ზომაცვლადი აქტივობების იძულება"</string> <string name="force_resizable_activities_summary" msgid="2490382056981583062">"მანიფესტის მნიშვნელობების მიუხედავად, მრავალი ფანჯრის რეჟიმისთვის ყველა აქტივობის ზომაცვლადად გადაქცევა."</string> - <string name="enable_freeform_support" msgid="8409932201445109106">"თავისუფალი ფორმის ფანჯრების ჩართვა (მოძველებული)"</string> - <string name="enable_freeform_support_summary" msgid="2242481082356957934">"თავისუფალი ფორმის ექსპერიმენტული მოძველებული ფანჯრების ჩართვა."</string> + <string name="enable_freeform_support" msgid="7599125687603914253">"თავისუფალი ფორმის მქონე ფანჯრების ჩართვა"</string> <string name="local_backup_password_title" msgid="4631017948933578709">"დესკტოპის სარეზერვო ასლის პაროლი"</string> <string name="local_backup_password_summary_none" msgid="7646898032616361714">"დესკტოპის სრული სარეზერვო ასლები ამჟამად დაცული არ არის"</string> <string name="local_backup_password_summary_change" msgid="1707357670383995567">"შეეხეთ დესკტოპის სრული სარეზერვო ასლების პაროლის შესაცვლელად ან წასაშლელად"</string> @@ -500,7 +499,8 @@ <string name="power_charging" msgid="6727132649743436802">"<xliff:g id="LEVEL">%1$s</xliff:g> - <xliff:g id="STATE">%2$s</xliff:g>"</string> <string name="power_remaining_charging_duration_only" msgid="8085099012811384899">"სრულ დატენვამდე დარჩენილია <xliff:g id="TIME">%1$s</xliff:g>"</string> <string name="power_charging_duration" msgid="6127154952524919719">"<xliff:g id="LEVEL">%1$s</xliff:g> — სრულ დატენვამდე დარჩენილია <xliff:g id="TIME">%2$s</xliff:g>"</string> - <string name="power_charging_limited" msgid="8202147604844938236">"<xliff:g id="LEVEL">%1$s</xliff:g> - დატენვა ოპტიმიზირებულია"</string> + <!-- no translation found for power_charging_limited (4144004473976005214) --> + <skip /> <string name="power_charging_future_paused" msgid="1809543660923642799">"<xliff:g id="LEVEL">%1$s</xliff:g> – იტენება"</string> <string name="power_fast_charging_duration_v2" msgid="3797735998640359490">"<xliff:g id="LEVEL">%1$s</xliff:g> - <xliff:g id="STATUS">%2$s</xliff:g> - სრულად დატენის დრო: <xliff:g id="TIME">%3$s</xliff:g>"</string> <string name="power_charging_duration_v2" msgid="2938998284074003248">"<xliff:g id="LEVEL">%1$s</xliff:g> - სრულად დატენის დრო: <xliff:g id="TIME">%2$s</xliff:g>"</string> diff --git a/packages/SettingsLib/res/values-kk/strings.xml b/packages/SettingsLib/res/values-kk/strings.xml index 536b624badef..b0b71efc100c 100644 --- a/packages/SettingsLib/res/values-kk/strings.xml +++ b/packages/SettingsLib/res/values-kk/strings.xml @@ -430,8 +430,7 @@ <string name="force_allow_on_external_summary" msgid="8525425782530728238">"Манифест мәндеріне қарамастан, кез келген қолданбаны сыртқы жадқа жазуға рұқсат беру"</string> <string name="force_resizable_activities" msgid="7143612144399959606">"Әрекеттердің өлшемін өзгертуге рұқсат ету"</string> <string name="force_resizable_activities_summary" msgid="2490382056981583062">"Манифест мәндеріне қарамастан, бірнеше терезе режимінде барлық әрекеттердің өлшемін өзгертуге рұқсат беру"</string> - <string name="enable_freeform_support" msgid="8409932201445109106">"Еркін пішінді терезелерге рұқсат беру (бұрынғы)"</string> - <string name="enable_freeform_support_summary" msgid="2242481082356957934">"Эксперименттік бұрынғы еркін пішінді терезелерді қолдауға рұқсат береді."</string> + <string name="enable_freeform_support" msgid="7599125687603914253">"Еркін пішінді терезелерге рұқсат беру"</string> <string name="local_backup_password_title" msgid="4631017948933578709">"Компьютердегі сақтық көшірме құпия сөзі"</string> <string name="local_backup_password_summary_none" msgid="7646898032616361714">"Компьютердегі толық сақтық көшірмелер қазір қорғалмаған."</string> <string name="local_backup_password_summary_change" msgid="1707357670383995567">"Үстелдік компьютердің толық сақтық көшірмелерінің кілтсөзін өзгерту немесе жою үшін түртіңіз"</string> @@ -496,7 +495,8 @@ <string name="power_charging" msgid="6727132649743436802">"<xliff:g id="LEVEL">%1$s</xliff:g> - <xliff:g id="STATE">%2$s</xliff:g>"</string> <string name="power_remaining_charging_duration_only" msgid="8085099012811384899">"Толық зарядталғанға дейін <xliff:g id="TIME">%1$s</xliff:g> қалды."</string> <string name="power_charging_duration" msgid="6127154952524919719">"<xliff:g id="LEVEL">%1$s</xliff:g>: толық зарядталуға <xliff:g id="TIME">%2$s</xliff:g> қалды"</string> - <string name="power_charging_limited" msgid="8202147604844938236">"<xliff:g id="LEVEL">%1$s</xliff:g> – зарядтау оңтайландырылды"</string> + <!-- no translation found for power_charging_limited (4144004473976005214) --> + <skip /> <string name="power_charging_future_paused" msgid="1809543660923642799">"<xliff:g id="LEVEL">%1$s</xliff:g> – Зарядталып жатыр"</string> <string name="power_fast_charging_duration_v2" msgid="3797735998640359490">"<xliff:g id="LEVEL">%1$s</xliff:g> - <xliff:g id="STATUS">%2$s</xliff:g> - Зарядталып болады: <xliff:g id="TIME">%3$s</xliff:g>"</string> <string name="power_charging_duration_v2" msgid="2938998284074003248">"<xliff:g id="LEVEL">%1$s</xliff:g> - Толық заряд алуға қалған уақыт: <xliff:g id="TIME">%2$s</xliff:g>"</string> diff --git a/packages/SettingsLib/res/values-km/strings.xml b/packages/SettingsLib/res/values-km/strings.xml index baef5d87dadf..577a2aead014 100644 --- a/packages/SettingsLib/res/values-km/strings.xml +++ b/packages/SettingsLib/res/values-km/strings.xml @@ -430,8 +430,7 @@ <string name="force_allow_on_external_summary" msgid="8525425782530728238">"ធ្វើឲ្យកម្មវិធីទាំងឡាយមានសិទ្ធិសរសេរទៅកាន់ឧបករណ៍ផ្ទុកខាងក្រៅ ដោយមិនគិតពីតម្លៃមេនីហ្វេសថ៍"</string> <string name="force_resizable_activities" msgid="7143612144399959606">"បង្ខំឲ្យសកម្មភាពអាចប្តូរទំហំបាន"</string> <string name="force_resizable_activities_summary" msgid="2490382056981583062">"ធ្វើឲ្យសកម្មភាពទាំងអស់អាចប្តូរទំហំបានសម្រាប់ពហុវិនដូ ដោយមិនគិតពីតម្លៃមេនីហ្វេសថ៍។"</string> - <string name="enable_freeform_support" msgid="8409932201445109106">"បើកវិនដូទម្រង់សេរី (ចាស់)"</string> - <string name="enable_freeform_support_summary" msgid="2242481082356957934">"បើកជំនួយសម្រាប់វិនដូទម្រង់សេរីចាស់ក្នុងដំណាក់កាលពិសោធន៍។"</string> + <string name="enable_freeform_support" msgid="7599125687603914253">"បើកដំណើរការផ្ទាំងវិនដូទម្រង់សេរី"</string> <string name="local_backup_password_title" msgid="4631017948933578709">"ពាក្យសម្ងាត់បម្រុងទុកលើកុំព្យូទ័រ"</string> <string name="local_backup_password_summary_none" msgid="7646898032616361714">"បច្ចុប្បន្ន ការបម្រុងទុកពេញលេញនៅលើកុំព្យូទ័រមិនត្រូវបានការពារទេ"</string> <string name="local_backup_password_summary_change" msgid="1707357670383995567">"ប៉ះដើម្បីប្ដូរ ឬយកពាក្យសម្ងាត់ចេញសម្រាប់ការបម្រុងទុកពេញលេញលើកុំព្យូទ័រ"</string> @@ -496,7 +495,8 @@ <string name="power_charging" msgid="6727132649743436802">"<xliff:g id="LEVEL">%1$s</xliff:g> - <xliff:g id="STATE">%2$s</xliff:g>"</string> <string name="power_remaining_charging_duration_only" msgid="8085099012811384899">"<xliff:g id="TIME">%1$s</xliff:g> ទៀតទើបពេញ"</string> <string name="power_charging_duration" msgid="6127154952524919719">"<xliff:g id="LEVEL">%1$s</xliff:g> - នៅសល់ <xliff:g id="TIME">%2$s</xliff:g> ទៀតទើបពេញ"</string> - <string name="power_charging_limited" msgid="8202147604844938236">"<xliff:g id="LEVEL">%1$s</xliff:g> - បានបង្កើនប្រសិទ្ធភាពនៃការសាក"</string> + <!-- no translation found for power_charging_limited (4144004473976005214) --> + <skip /> <string name="power_charging_future_paused" msgid="1809543660923642799">"<xliff:g id="LEVEL">%1$s</xliff:g> - កំពុងសាកថ្ម"</string> <string name="power_fast_charging_duration_v2" msgid="3797735998640359490">"<xliff:g id="LEVEL">%1$s</xliff:g> - <xliff:g id="STATUS">%2$s</xliff:g> - ពេញនៅម៉ោង <xliff:g id="TIME">%3$s</xliff:g>"</string> <string name="power_charging_duration_v2" msgid="2938998284074003248">"<xliff:g id="LEVEL">%1$s</xliff:g> - សាកថ្មពេញនៅម៉ោង <xliff:g id="TIME">%2$s</xliff:g>"</string> diff --git a/packages/SettingsLib/res/values-kn/strings.xml b/packages/SettingsLib/res/values-kn/strings.xml index a203ea785e12..69e8bffcfc81 100644 --- a/packages/SettingsLib/res/values-kn/strings.xml +++ b/packages/SettingsLib/res/values-kn/strings.xml @@ -430,8 +430,7 @@ <string name="force_allow_on_external_summary" msgid="8525425782530728238">"ಮ್ಯಾನಿಫೆಸ್ಟ್ ಮೌಲ್ಯಗಳು ಯಾವುದೇ ಆಗಿದ್ದರೂ, ಬಾಹ್ಯ ಸಂಗ್ರಹಣೆಗೆ ಬರೆಯಲು ಯಾವುದೇ ಅಪ್ಲಿಕೇಶನ್ ಅನ್ನು ಅರ್ಹಗೊಳಿಸುತ್ತದೆ"</string> <string name="force_resizable_activities" msgid="7143612144399959606">"ಚಟುವಟಿಕೆಗಳನ್ನು ಮರುಗಾತ್ರಗೊಳಿಸುವಂತೆ ಒತ್ತಾಯ ಮಾಡಿ"</string> <string name="force_resizable_activities_summary" msgid="2490382056981583062">"ಮ್ಯಾನಿಫೆಸ್ಟ್ ಮೌಲ್ಯಗಳನ್ನು ಪರಿಗಣಿಸದೇ, ಬಹು-ವಿಂಡೊಗೆ ಎಲ್ಲಾ ಚಟುವಟಿಕೆಗಳನ್ನು ಮರುಗಾತ್ರಗೊಳಿಸುವಂತೆ ಮಾಡಿ."</string> - <string name="enable_freeform_support" msgid="8409932201445109106">"ಫ್ರೀಫಾರ್ಮ್ ವಿಂಡೋಗಳನ್ನು ಸಕ್ರಿಯಗೊಳಿಸಿ (ಲೆಗಸಿ)"</string> - <string name="enable_freeform_support_summary" msgid="2242481082356957934">"ಪ್ರಾಯೋಗಿಕ ಲೆಗಸಿ ಫ್ರೀಫಾರ್ಮ್ ವಿಂಡೋಗಳಿಗೆ ಬೆಂಬಲವನ್ನು ಸಕ್ರಿಯಗೊಳಿಸಿ."</string> + <string name="enable_freeform_support" msgid="7599125687603914253">"ಮುಕ್ತಸ್ವರೂಪದ ವಿಂಡೊಗಳನ್ನು ಸಕ್ರಿಯಗೊಳಿಸಿ"</string> <string name="local_backup_password_title" msgid="4631017948933578709">"ಡೆಸ್ಕ್ಟಾಪ್ ಬ್ಯಾಕಪ್ ಪಾಸ್ವರ್ಡ್"</string> <string name="local_backup_password_summary_none" msgid="7646898032616361714">"ಡೆಸ್ಕ್ಟಾಪ್ ಪೂರ್ಣ ಬ್ಯಾಕಪ್ಗಳನ್ನು ಪ್ರಸ್ತುತ ರಕ್ಷಿಸಲಾಗಿಲ್ಲ"</string> <string name="local_backup_password_summary_change" msgid="1707357670383995567">"ಡೆಸ್ಕ್ಟಾಪ್ನ ಪೂರ್ಣ ಬ್ಯಾಕಪ್ಗಳಿಗೆ ಪಾಸ್ವರ್ಡ್ ಬದಲಾಯಿಸಲು ಅಥವಾ ತೆಗೆದುಹಾಕಲು ಟ್ಯಾಪ್ ಮಾಡಿ"</string> @@ -496,7 +495,8 @@ <string name="power_charging" msgid="6727132649743436802">"<xliff:g id="LEVEL">%1$s</xliff:g> - <xliff:g id="STATE">%2$s</xliff:g>"</string> <string name="power_remaining_charging_duration_only" msgid="8085099012811384899">"<xliff:g id="TIME">%1$s</xliff:g> - ಸಮಯದಲ್ಲಿ ಪೂರ್ತಿ ಚಾರ್ಜ್ ಆಗುತ್ತದೆ"</string> <string name="power_charging_duration" msgid="6127154952524919719">"<xliff:g id="LEVEL">%1$s</xliff:g> - <xliff:g id="TIME">%2$s</xliff:g> ಸಮಯದಲ್ಲಿ ಪೂರ್ತಿ ಚಾರ್ಜ್ ಆಗುತ್ತದೆ"</string> - <string name="power_charging_limited" msgid="8202147604844938236">"<xliff:g id="LEVEL">%1$s</xliff:g> - ಚಾರ್ಜಿಂಗ್ ಅನ್ನು ಆಪ್ಟಿಮೈಸ್ ಮಾಡಲಾಗಿದೆ"</string> + <!-- no translation found for power_charging_limited (4144004473976005214) --> + <skip /> <string name="power_charging_future_paused" msgid="1809543660923642799">"<xliff:g id="LEVEL">%1$s</xliff:g> - ಚಾರ್ಜಿಂಗ್ ಆಗುತ್ತಿದೆ"</string> <string name="power_fast_charging_duration_v2" msgid="3797735998640359490">"<xliff:g id="LEVEL">%1$s</xliff:g> - <xliff:g id="STATUS">%2$s</xliff:g> - <xliff:g id="TIME">%3$s</xliff:g> ವೇಳೆಗೆ ಭರ್ತಿಯಾಗುತ್ತದೆ"</string> <string name="power_charging_duration_v2" msgid="2938998284074003248">"<xliff:g id="LEVEL">%1$s</xliff:g> - <xliff:g id="TIME">%2$s</xliff:g> ವೇಳೆಗೆ ಸಂಪೂರ್ಣವಾಗಿ ಚಾರ್ಜ್ ಆಗುತ್ತದೆ"</string> diff --git a/packages/SettingsLib/res/values-ko/strings.xml b/packages/SettingsLib/res/values-ko/strings.xml index 67f1ecdb8e85..af4f37b42adf 100644 --- a/packages/SettingsLib/res/values-ko/strings.xml +++ b/packages/SettingsLib/res/values-ko/strings.xml @@ -430,8 +430,7 @@ <string name="force_allow_on_external_summary" msgid="8525425782530728238">"매니페스트 값과 관계없이 모든 앱이 외부 저장소에 작성되도록 허용"</string> <string name="force_resizable_activities" msgid="7143612144399959606">"활동의 크기가 조정 가능하도록 설정"</string> <string name="force_resizable_activities_summary" msgid="2490382056981583062">"모든 활동을 매니페스트 값에 관계없이 멀티 윈도우용으로 크기 조정 가능하도록 설정"</string> - <string name="enable_freeform_support" msgid="8409932201445109106">"자유 형식 창 사용(레거시)"</string> - <string name="enable_freeform_support_summary" msgid="2242481082356957934">"실험적인 레거시 자유 형식 창에 대한 지원을 사용하도록 설정합니다."</string> + <string name="enable_freeform_support" msgid="7599125687603914253">"자유 형식 창 사용"</string> <string name="local_backup_password_title" msgid="4631017948933578709">"데스크톱 백업 비밀번호"</string> <string name="local_backup_password_summary_none" msgid="7646898032616361714">"데스크톱 전체 백업에 비밀번호가 설정되어 있지 않음"</string> <string name="local_backup_password_summary_change" msgid="1707357670383995567">"데스크톱 전체 백업에 대한 비밀번호를 변경하거나 삭제하려면 탭하세요."</string> @@ -496,7 +495,8 @@ <string name="power_charging" msgid="6727132649743436802">"<xliff:g id="LEVEL">%1$s</xliff:g> - <xliff:g id="STATE">%2$s</xliff:g>"</string> <string name="power_remaining_charging_duration_only" msgid="8085099012811384899">"<xliff:g id="TIME">%1$s</xliff:g> 후 충전 완료"</string> <string name="power_charging_duration" msgid="6127154952524919719">"<xliff:g id="LEVEL">%1$s</xliff:g>: <xliff:g id="TIME">%2$s</xliff:g> 후 충전 완료"</string> - <string name="power_charging_limited" msgid="8202147604844938236">"<xliff:g id="LEVEL">%1$s</xliff:g> - 충전 최적화됨"</string> + <!-- no translation found for power_charging_limited (4144004473976005214) --> + <skip /> <string name="power_charging_future_paused" msgid="1809543660923642799">"<xliff:g id="LEVEL">%1$s</xliff:g> ‑ 충전 중"</string> <string name="power_fast_charging_duration_v2" msgid="3797735998640359490">"<xliff:g id="LEVEL">%1$s</xliff:g> - <xliff:g id="STATUS">%2$s</xliff:g> - <xliff:g id="TIME">%3$s</xliff:g>에 완전히 충전됨"</string> <string name="power_charging_duration_v2" msgid="2938998284074003248">"<xliff:g id="LEVEL">%1$s</xliff:g> - <xliff:g id="TIME">%2$s</xliff:g>에 완전히 충전됨"</string> diff --git a/packages/SettingsLib/res/values-ky/strings.xml b/packages/SettingsLib/res/values-ky/strings.xml index 73532645873a..95d35f30c1a7 100644 --- a/packages/SettingsLib/res/values-ky/strings.xml +++ b/packages/SettingsLib/res/values-ky/strings.xml @@ -430,8 +430,7 @@ <string name="force_allow_on_external_summary" msgid="8525425782530728238">"Манифест маанилерине карабастан бардык колдонмолорду тышкы сактагычка сактоого уруксат берет"</string> <string name="force_resizable_activities" msgid="7143612144399959606">"Бир нече терезе режиминде өлчөмдү өзгөртүү"</string> <string name="force_resizable_activities_summary" msgid="2490382056981583062">"Бир нече терезе режиминде өлчөмдү өзгөртүүгө уруксат берет (манифесттин маанилерине карабастан)"</string> - <string name="enable_freeform_support" msgid="8409932201445109106">"Эркин формадагы терезелерди түзүүнү иштетүү (эски)"</string> - <string name="enable_freeform_support_summary" msgid="2242481082356957934">"Эркин формадагы эски терезелерди түзүү боюнча сынамык функциясы иштетилет."</string> + <string name="enable_freeform_support" msgid="7599125687603914253">"Эркин формадагы терезелерди түзүүнү иштетүү"</string> <string name="local_backup_password_title" msgid="4631017948933578709">"Камдык көчүрмөнүн сырсөзү"</string> <string name="local_backup_password_summary_none" msgid="7646898032616361714">"Толук камдык көчүрмөлөр учурда корголгон эмес"</string> <string name="local_backup_password_summary_change" msgid="1707357670383995567">"Иш тактасынын камдалган сырсөзүн өзгөртүү же алып салуу үчүн таптап коюңуз"</string> @@ -496,7 +495,8 @@ <string name="power_charging" msgid="6727132649743436802">"<xliff:g id="LEVEL">%1$s</xliff:g> - <xliff:g id="STATE">%2$s</xliff:g>"</string> <string name="power_remaining_charging_duration_only" msgid="8085099012811384899">"<xliff:g id="TIME">%1$s</xliff:g> кийин толук кубатталат"</string> <string name="power_charging_duration" msgid="6127154952524919719">"<xliff:g id="LEVEL">%1$s</xliff:g> – <xliff:g id="TIME">%2$s</xliff:g> кийин толук кубатталат"</string> - <string name="power_charging_limited" msgid="8202147604844938236">"<xliff:g id="LEVEL">%1$s</xliff:g> — Кубаттоо жакшыртылды"</string> + <!-- no translation found for power_charging_limited (4144004473976005214) --> + <skip /> <string name="power_charging_future_paused" msgid="1809543660923642799">"<xliff:g id="LEVEL">%1$s</xliff:g> - Кубатталууда"</string> <string name="power_fast_charging_duration_v2" msgid="3797735998640359490">"<xliff:g id="LEVEL">%1$s</xliff:g> - <xliff:g id="STATUS">%2$s</xliff:g> - Саат <xliff:g id="TIME">%3$s</xliff:g> кубатталып бүтөт"</string> <string name="power_charging_duration_v2" msgid="2938998284074003248">"<xliff:g id="LEVEL">%1$s</xliff:g> - <xliff:g id="TIME">%2$s</xliff:g> чейин толук кубатталат"</string> diff --git a/packages/SettingsLib/res/values-lo/strings.xml b/packages/SettingsLib/res/values-lo/strings.xml index 3680e8d13b1f..2bf96ad42bd1 100644 --- a/packages/SettingsLib/res/values-lo/strings.xml +++ b/packages/SettingsLib/res/values-lo/strings.xml @@ -430,8 +430,7 @@ <string name="force_allow_on_external_summary" msgid="8525425782530728238">"ເຮັດໃຫ້ທຸກແອັບມີສິດໄດ້ຮັບການຂຽນໃສ່ພື້ນທີ່ຈັດເກັບຂໍ້ມູນພາຍນອກ, ໂດຍບໍ່ຄຳນຶງເຖິງຄ່າ manifest"</string> <string name="force_resizable_activities" msgid="7143612144399959606">"ບັງຄັງໃຫ້ການເຄື່ອນໄຫວປ່ຽນຂະໜາດໄດ້"</string> <string name="force_resizable_activities_summary" msgid="2490382056981583062">"ເຮັດໃຫ້ທຸກການເຄື່ອນໄຫວສາມາດປັບຂະໜາດໄດ້ສຳລັບຫຼາຍໜ້າຈໍ, ໂດຍບໍ່ຄຳນຶງເຖິງຄ່າ manifest."</string> - <string name="enable_freeform_support" msgid="8409932201445109106">"ເປີດການນຳໃຊ້ໜ້າຈໍຮູບແບບອິດສະຫຼະ (ແບບເກົ່າ)"</string> - <string name="enable_freeform_support_summary" msgid="2242481082356957934">"ເປີດການນຳໃຊ້ການຮອງຮັບໜ້າຈໍຮູບແບບອິດສະຫຼະແບບເກົ່າເວີຊັນທົດລອງ."</string> + <string name="enable_freeform_support" msgid="7599125687603914253">"ເປີດໃຊ້ໜ້າຈໍຮູບແບບອິດສະຫຼະ"</string> <string name="local_backup_password_title" msgid="4631017948933578709">"ລະຫັດຜ່ານການສຳຮອງຂໍ້ມູນເດັສທັອບ"</string> <string name="local_backup_password_summary_none" msgid="7646898032616361714">"ການສຳຮອງຂໍ້ມູນເຕັມຮູບແບບໃນເດັສທັອບຍັງບໍ່ໄດ້ຮັບການປ້ອງກັນໃນເວລານີ້"</string> <string name="local_backup_password_summary_change" msgid="1707357670383995567">"ແຕະເພື່ອປ່ຽນ ຫຼື ລຶບລະຫັດຂອງການສຳຮອງຂໍ້ມູນເຕັມຮູບແບບໃນເດັສທັອບ"</string> @@ -496,7 +495,8 @@ <string name="power_charging" msgid="6727132649743436802">"<xliff:g id="LEVEL">%1$s</xliff:g> - <xliff:g id="STATE">%2$s</xliff:g>"</string> <string name="power_remaining_charging_duration_only" msgid="8085099012811384899">"ຍັງເຫຼືອອີກ <xliff:g id="TIME">%1$s</xliff:g> ຈຶ່ງຈະສາກເຕັມ"</string> <string name="power_charging_duration" msgid="6127154952524919719">"ຍັງເຫຼືອອີກ <xliff:g id="LEVEL">%1$s</xliff:g> - <xliff:g id="TIME">%2$s</xliff:g> ຈຶ່ງຈະສາກເຕັມ"</string> - <string name="power_charging_limited" msgid="8202147604844938236">"<xliff:g id="LEVEL">%1$s</xliff:g> - ການສາກຖືກປັບໃຫ້ເໝາະສົມແລ້ວ"</string> + <!-- no translation found for power_charging_limited (4144004473976005214) --> + <skip /> <string name="power_charging_future_paused" msgid="1809543660923642799">"<xliff:g id="LEVEL">%1$s</xliff:g> - ກຳລັງສາກໄຟ"</string> <string name="power_fast_charging_duration_v2" msgid="3797735998640359490">"<xliff:g id="LEVEL">%1$s</xliff:g> - <xliff:g id="STATUS">%2$s</xliff:g> - ຈະເຕັມພາຍໃນ <xliff:g id="TIME">%3$s</xliff:g>"</string> <string name="power_charging_duration_v2" msgid="2938998284074003248">"<xliff:g id="LEVEL">%1$s</xliff:g> - ຈະສາກເຕັມພາຍໃນ <xliff:g id="TIME">%2$s</xliff:g>"</string> diff --git a/packages/SettingsLib/res/values-lt/strings.xml b/packages/SettingsLib/res/values-lt/strings.xml index 4f0d6b082479..6363cdbbdbc3 100644 --- a/packages/SettingsLib/res/values-lt/strings.xml +++ b/packages/SettingsLib/res/values-lt/strings.xml @@ -430,8 +430,7 @@ <string name="force_allow_on_external_summary" msgid="8525425782530728238">"Nustatoma, kad visas programas būtų galima įrašyti į išorinę saugyklą, nepaisant aprašo verčių"</string> <string name="force_resizable_activities" msgid="7143612144399959606">"Priv. nust., kad veiksm. b. g. atl. kelių d. lang."</string> <string name="force_resizable_activities_summary" msgid="2490382056981583062">"Nustatyti, kad visus veiksmus būtų galima atlikti kelių dydžių languose, nepaisant aprašo verčių."</string> - <string name="enable_freeform_support" msgid="8409932201445109106">"Įgalinti laisvos formos langus (pasenę)"</string> - <string name="enable_freeform_support_summary" msgid="2242481082356957934">"Įgalinti eksperimentinių pasenusių laisvos formos langų palaikymą."</string> + <string name="enable_freeform_support" msgid="7599125687603914253">"Įgalinti laisvos formos langus"</string> <string name="local_backup_password_title" msgid="4631017948933578709">"Viet. atsrg. kop. slapt."</string> <string name="local_backup_password_summary_none" msgid="7646898032616361714">"Šiuo metu visos vietinės atsarginės kopijos neapsaugotos"</string> <string name="local_backup_password_summary_change" msgid="1707357670383995567">"Jei norite pakeisti ar pašalinti visų stalinio kompiuterio atsarginių kopijų slaptažodį, palieskite"</string> @@ -496,7 +495,8 @@ <string name="power_charging" msgid="6727132649743436802">"<xliff:g id="LEVEL">%1$s</xliff:g> – <xliff:g id="STATE">%2$s</xliff:g>"</string> <string name="power_remaining_charging_duration_only" msgid="8085099012811384899">"Liko <xliff:g id="TIME">%1$s</xliff:g>, kol bus visiškai įkrauta"</string> <string name="power_charging_duration" msgid="6127154952524919719">"<xliff:g id="LEVEL">%1$s</xliff:g> – liko <xliff:g id="TIME">%2$s</xliff:g>, kol bus visiškai įkrauta"</string> - <string name="power_charging_limited" msgid="8202147604844938236">"<xliff:g id="LEVEL">%1$s</xliff:g> – įkrovimas optimizuotas"</string> + <!-- no translation found for power_charging_limited (4144004473976005214) --> + <skip /> <string name="power_charging_future_paused" msgid="1809543660923642799">"<xliff:g id="LEVEL">%1$s</xliff:g> – įkraunama"</string> <string name="power_fast_charging_duration_v2" msgid="3797735998640359490">"<xliff:g id="LEVEL">%1$s</xliff:g> – <xliff:g id="STATUS">%2$s</xliff:g> – bus visiškai įkrauta <xliff:g id="TIME">%3$s</xliff:g>"</string> <string name="power_charging_duration_v2" msgid="2938998284074003248">"<xliff:g id="LEVEL">%1$s</xliff:g> – bus visiškai įkrauta <xliff:g id="TIME">%2$s</xliff:g>"</string> diff --git a/packages/SettingsLib/res/values-lv/strings.xml b/packages/SettingsLib/res/values-lv/strings.xml index e571b84ae681..2b82cdbcb82a 100644 --- a/packages/SettingsLib/res/values-lv/strings.xml +++ b/packages/SettingsLib/res/values-lv/strings.xml @@ -430,8 +430,7 @@ <string name="force_allow_on_external_summary" msgid="8525425782530728238">"Ļauj jebkuru lietotni ierakstīt ārējā krātuvē neatkarīgi no manifesta vērtības."</string> <string name="force_resizable_activities" msgid="7143612144399959606">"Pielāgot darbības"</string> <string name="force_resizable_activities_summary" msgid="2490382056981583062">"Pielāgot visas darbības vairāku logu režīmam neatkarīgi no vērtībām manifestā."</string> - <string name="enable_freeform_support" msgid="8409932201445109106">"Iespējot brīvās formas logus (mantots režīms)"</string> - <string name="enable_freeform_support_summary" msgid="2242481082356957934">"Iespējot atbalstu eksperimentālajam, mantotajam brīvās formas logu režīmam."</string> + <string name="enable_freeform_support" msgid="7599125687603914253">"Iespējot brīvās formas logus"</string> <string name="local_backup_password_title" msgid="4631017948933578709">"Datora dublējuma parole"</string> <string name="local_backup_password_summary_none" msgid="7646898032616361714">"Darbvirsmas pilnie dublējumi pašlaik nav aizsargāti."</string> <string name="local_backup_password_summary_change" msgid="1707357670383995567">"Pieskarieties, lai mainītu vai noņemtu paroli pilniem datora dublējumiem."</string> @@ -496,7 +495,8 @@ <string name="power_charging" msgid="6727132649743436802">"<xliff:g id="LEVEL">%1$s</xliff:g> — <xliff:g id="STATE">%2$s</xliff:g>"</string> <string name="power_remaining_charging_duration_only" msgid="8085099012811384899">"<xliff:g id="TIME">%1$s</xliff:g> līdz pilnai uzlādei"</string> <string name="power_charging_duration" msgid="6127154952524919719">"<xliff:g id="LEVEL">%1$s</xliff:g> — <xliff:g id="TIME">%2$s</xliff:g> līdz pilnai uzlādei"</string> - <string name="power_charging_limited" msgid="8202147604844938236">"<xliff:g id="LEVEL">%1$s</xliff:g> — uzlāde optimizēta"</string> + <!-- no translation found for power_charging_limited (4144004473976005214) --> + <skip /> <string name="power_charging_future_paused" msgid="1809543660923642799">"<xliff:g id="LEVEL">%1$s</xliff:g> — notiek uzlāde"</string> <string name="power_fast_charging_duration_v2" msgid="3797735998640359490">"<xliff:g id="LEVEL">%1$s</xliff:g> — <xliff:g id="STATUS">%2$s</xliff:g>. Tiks pilnībā uzlādēts līdz plkst. <xliff:g id="TIME">%3$s</xliff:g>"</string> <string name="power_charging_duration_v2" msgid="2938998284074003248">"<xliff:g id="LEVEL">%1$s</xliff:g> — tiks pilnībā uzlādēts līdz plkst. <xliff:g id="TIME">%2$s</xliff:g>"</string> diff --git a/packages/SettingsLib/res/values-mk/strings.xml b/packages/SettingsLib/res/values-mk/strings.xml index ab30556856b7..b135afa61ffd 100644 --- a/packages/SettingsLib/res/values-mk/strings.xml +++ b/packages/SettingsLib/res/values-mk/strings.xml @@ -430,8 +430,7 @@ <string name="force_allow_on_external_summary" msgid="8525425782530728238">"Сите апликации ќе бидат подобни за запишување во надворешната меморија, независно од вредностите на манифестот"</string> <string name="force_resizable_activities" msgid="7143612144399959606">"Наметни променлива големина на активностите"</string> <string name="force_resizable_activities_summary" msgid="2490382056981583062">"Сите активности ќе имаат променлива големина во режимот со повеќе прозорци, независно од вредностите на манифестот."</string> - <string name="enable_freeform_support" msgid="8409932201445109106">"Овозможи прозорци со менлива големина (застарено)"</string> - <string name="enable_freeform_support_summary" msgid="2242481082356957934">"Овозможете поддршка за експериментални застарени прозорци со менлива големина."</string> + <string name="enable_freeform_support" msgid="7599125687603914253">"Овозможи прозорци со слободна форма"</string> <string name="local_backup_password_title" msgid="4631017948933578709">"Лозинка за бекап на компјутер"</string> <string name="local_backup_password_summary_none" msgid="7646898032616361714">"Целосниот бекап на компјутерот во моментов не е заштитен"</string> <string name="local_backup_password_summary_change" msgid="1707357670383995567">"Допрете за да се промени или отстрани лозинката за целосен бекап на компјутерот"</string> @@ -496,7 +495,8 @@ <string name="power_charging" msgid="6727132649743436802">"<xliff:g id="LEVEL">%1$s</xliff:g> – <xliff:g id="STATE">%2$s</xliff:g>"</string> <string name="power_remaining_charging_duration_only" msgid="8085099012811384899">"<xliff:g id="TIME">%1$s</xliff:g> до полна батерија"</string> <string name="power_charging_duration" msgid="6127154952524919719">"<xliff:g id="LEVEL">%1$s</xliff:g> – <xliff:g id="TIME">%2$s</xliff:g> до полна батерија"</string> - <string name="power_charging_limited" msgid="8202147604844938236">"<xliff:g id="LEVEL">%1$s</xliff:g> – полнењето е оптимизирано"</string> + <!-- no translation found for power_charging_limited (4144004473976005214) --> + <skip /> <string name="power_charging_future_paused" msgid="1809543660923642799">"<xliff:g id="LEVEL">%1$s</xliff:g> – се полни"</string> <string name="power_fast_charging_duration_v2" msgid="3797735998640359490">"<xliff:g id="LEVEL">%1$s</xliff:g> – <xliff:g id="STATUS">%2$s</xliff:g> – Ќе се наполни целосно до <xliff:g id="TIME">%3$s</xliff:g>"</string> <string name="power_charging_duration_v2" msgid="2938998284074003248">"<xliff:g id="LEVEL">%1$s</xliff:g> – Ќе се наполни целосно до <xliff:g id="TIME">%2$s</xliff:g>"</string> diff --git a/packages/SettingsLib/res/values-ml/strings.xml b/packages/SettingsLib/res/values-ml/strings.xml index d19069157b45..5fa8961f0f27 100644 --- a/packages/SettingsLib/res/values-ml/strings.xml +++ b/packages/SettingsLib/res/values-ml/strings.xml @@ -430,8 +430,7 @@ <string name="force_allow_on_external_summary" msgid="8525425782530728238">"മാനിഫെസ്റ്റ് മൂല്യങ്ങൾ പരിഗണിക്കാതെ, ബാഹ്യ സ്റ്റോറേജിലേക്ക് എഴുതപ്പെടുന്നതിന് ഏതൊരു ആപ്പിനെയും യോഗ്യമാക്കുന്നു"</string> <string name="force_resizable_activities" msgid="7143612144399959606">"വലുപ്പം മാറ്റാൻ പ്രവർത്തനങ്ങളെ നിർബന്ധിക്കുക"</string> <string name="force_resizable_activities_summary" msgid="2490382056981583062">"മാനിഫെസ്റ്റ് മൂല്യങ്ങൾ പരിഗണിക്കാതെ, എല്ലാ ആക്ടിവിറ്റികളെയും മൾട്ടി-വിൻഡോയ്ക്കായി വലുപ്പം മാറ്റുക."</string> - <string name="enable_freeform_support" msgid="8409932201445109106">"ഫ്രീഫോം വിൻഡോകൾ പ്രവർത്തനക്ഷമമാക്കുക (ലെഗസി)"</string> - <string name="enable_freeform_support_summary" msgid="2242481082356957934">"പരീക്ഷണാത്മക ലെഗസി ഫ്രീഫോം വിൻഡോകൾക്കുള്ള പിന്തുണ പ്രവർത്തനക്ഷമമാക്കുക."</string> + <string name="enable_freeform_support" msgid="7599125687603914253">"ഫ്രീഫോം വിൻഡോകൾ പ്രവർത്തനക്ഷമമാക്കുക"</string> <string name="local_backup_password_title" msgid="4631017948933578709">"ഡെസ്ക്ടോപ്പ് ബാക്കപ്പ് പാസ്വേഡ്"</string> <string name="local_backup_password_summary_none" msgid="7646898032616361714">"ഡെസ്ക്ടോപ്പ് പൂർണ്ണ ബാക്കപ്പുകൾ നിലവിൽ പരിരക്ഷിച്ചിട്ടില്ല"</string> <string name="local_backup_password_summary_change" msgid="1707357670383995567">"ഡെസ്ക്ടോപ്പ് പൂർണ്ണ ബാക്കപ്പുകൾക്കായി പാസ്വേഡുകൾ മാറ്റാനോ നീക്കംചെയ്യാനോ ടാപ്പുചെയ്യുക"</string> @@ -496,7 +495,8 @@ <string name="power_charging" msgid="6727132649743436802">"<xliff:g id="LEVEL">%1$s</xliff:g> - <xliff:g id="STATE">%2$s</xliff:g>"</string> <string name="power_remaining_charging_duration_only" msgid="8085099012811384899">"പൂർണ്ണമാകാൻ <xliff:g id="TIME">%1$s</xliff:g> ശേഷിക്കുന്നു"</string> <string name="power_charging_duration" msgid="6127154952524919719">"<xliff:g id="LEVEL">%1$s</xliff:g> - പൂർണ്ണമാകാൻ <xliff:g id="TIME">%2$s</xliff:g> ശേഷിക്കുന്നു"</string> - <string name="power_charging_limited" msgid="8202147604844938236">"<xliff:g id="LEVEL">%1$s</xliff:g> - ചാർജിംഗ് ഒപ്റ്റിമൈസ് ചെയ്തു"</string> + <!-- no translation found for power_charging_limited (4144004473976005214) --> + <skip /> <string name="power_charging_future_paused" msgid="1809543660923642799">"<xliff:g id="LEVEL">%1$s</xliff:g> ‑ ചാർജ് ചെയ്യുന്നു"</string> <string name="power_fast_charging_duration_v2" msgid="3797735998640359490">"<xliff:g id="LEVEL">%1$s</xliff:g> - <xliff:g id="STATUS">%2$s</xliff:g> - <xliff:g id="TIME">%3$s</xliff:g>-നകം പൂർണ്ണമാകും"</string> <string name="power_charging_duration_v2" msgid="2938998284074003248">"<xliff:g id="LEVEL">%1$s</xliff:g> - <xliff:g id="TIME">%2$s</xliff:g>-നകം പൂർണ്ണമായി ചാർജ് ചെയ്യും"</string> diff --git a/packages/SettingsLib/res/values-mn/strings.xml b/packages/SettingsLib/res/values-mn/strings.xml index c0a79392e0f3..388ea6f4fb98 100644 --- a/packages/SettingsLib/res/values-mn/strings.xml +++ b/packages/SettingsLib/res/values-mn/strings.xml @@ -430,8 +430,7 @@ <string name="force_allow_on_external_summary" msgid="8525425782530728238">"Манифест утгыг нь үл хамааран дурын апп-г гадаад санах ойд бичих боломжтой болгодог"</string> <string name="force_resizable_activities" msgid="7143612144399959606">"Үйл ажиллагааны хэмжээг өөрчилж болохуйц болгох"</string> <string name="force_resizable_activities_summary" msgid="2490382056981583062">"Тодорхойлогч файлын утгыг үл хамааран, бүх үйл ажиллагааны хэмжээг олон цонхонд өөрчилж болохуйц болгоно уу."</string> - <string name="enable_freeform_support" msgid="8409932201445109106">"Чөлөөт хэлбэрийн цонхыг идэвхжүүлэх (уламжлалт)"</string> - <string name="enable_freeform_support_summary" msgid="2242481082356957934">"Туршилтын чөлөөт хэлбэрийн уламжлалт цонхны дэмжлэгийг идэвхжүүлнэ үү."</string> + <string name="enable_freeform_support" msgid="7599125687603914253">"Чөлөөт хэлбэрийн цонхыг идэвхжүүлэх"</string> <string name="local_backup_password_title" msgid="4631017948933578709">"Компьютерын нөөцлөлтийн нууц үг"</string> <string name="local_backup_password_summary_none" msgid="7646898032616361714">"Компьютерын бүрэн нөөцлөлт одоогоор хамгаалалтгүй байна"</string> <string name="local_backup_password_summary_change" msgid="1707357670383995567">"Компьютерийн бүтэн нөөцлөлтийн нууц үгийг өөрчлөх, устгах бол дарна уу"</string> @@ -496,7 +495,8 @@ <string name="power_charging" msgid="6727132649743436802">"<xliff:g id="LEVEL">%1$s</xliff:g> - <xliff:g id="STATE">%2$s</xliff:g>"</string> <string name="power_remaining_charging_duration_only" msgid="8085099012811384899">"Дүүрэх хүртэл <xliff:g id="TIME">%1$s</xliff:g> үлдсэн"</string> <string name="power_charging_duration" msgid="6127154952524919719">"<xliff:g id="LEVEL">%1$s</xliff:g> - дүүрэх хүртэл <xliff:g id="TIME">%2$s</xliff:g> үлдсэн"</string> - <string name="power_charging_limited" msgid="8202147604844938236">"<xliff:g id="LEVEL">%1$s</xliff:g> - Цэнэглэх явцыг оновчилсон"</string> + <!-- no translation found for power_charging_limited (4144004473976005214) --> + <skip /> <string name="power_charging_future_paused" msgid="1809543660923642799">"<xliff:g id="LEVEL">%1$s</xliff:g> - Цэнэглэж байна"</string> <string name="power_fast_charging_duration_v2" msgid="3797735998640359490">"<xliff:g id="LEVEL">%1$s</xliff:g> - <xliff:g id="STATUS">%2$s</xliff:g> - <xliff:g id="TIME">%3$s</xliff:g> гэхэд дүүрнэ"</string> <string name="power_charging_duration_v2" msgid="2938998284074003248">"<xliff:g id="LEVEL">%1$s</xliff:g> - <xliff:g id="TIME">%2$s</xliff:g> гэхэд бүрэн цэнэглэгдэнэ"</string> diff --git a/packages/SettingsLib/res/values-mr/strings.xml b/packages/SettingsLib/res/values-mr/strings.xml index 4842a9925170..063b7d13799a 100644 --- a/packages/SettingsLib/res/values-mr/strings.xml +++ b/packages/SettingsLib/res/values-mr/strings.xml @@ -430,8 +430,7 @@ <string name="force_allow_on_external_summary" msgid="8525425782530728238">"मॅनिफेस्ट मूल्ये काहीही असू देत, कोणत्याही अॅपला बाह्य स्टोरेजवर राइट करण्यासाठी पात्र बनविते"</string> <string name="force_resizable_activities" msgid="7143612144399959606">"ॲक्टिव्हिटीचा आकार बदलण्यायोग्य होण्याची सक्ती करा"</string> <string name="force_resizable_activities_summary" msgid="2490382056981583062">"मॅनिफेस्ट मूल्ये काहीही असू देत, एकाहून अधिक विंडोसाठी सर्व अॅक्टिव्हिटीचा आकार बदलण्यायोग्य करा."</string> - <string name="enable_freeform_support" msgid="8409932201445109106">"फ्रीफॉर्म विंडो सुरू करा (लेगसी)"</string> - <string name="enable_freeform_support_summary" msgid="2242481082356957934">"प्रायोगिक लेगसी फ्रीफॉर्म विंडोसाठी सपोर्ट सुरू करा."</string> + <string name="enable_freeform_support" msgid="7599125687603914253">"freeform windows सुरू करा"</string> <string name="local_backup_password_title" msgid="4631017948933578709">"डेस्कटॉप बॅकअप पासवर्ड"</string> <string name="local_backup_password_summary_none" msgid="7646898032616361714">"डेस्कटॉप पूर्ण बॅक अप सध्या संरक्षित नाहीत"</string> <string name="local_backup_password_summary_change" msgid="1707357670383995567">"डेस्कटॉपच्या पूर्ण बॅकअपसाठी असलेला पासवर्ड बदलण्यासाठी किंवा काढण्यासाठी टॅप करा"</string> @@ -495,8 +494,9 @@ <string name="power_remaining_only_more_than_subtext" msgid="4873750633368888062">"<xliff:g id="TIME_REMAINING">%1$s</xliff:g> पेक्षा जास्त शिल्लक आहे"</string> <string name="power_charging" msgid="6727132649743436802">"<xliff:g id="LEVEL">%1$s</xliff:g> - <xliff:g id="STATE">%2$s</xliff:g>"</string> <string name="power_remaining_charging_duration_only" msgid="8085099012811384899">"पूर्ण चार्ज होण्यासाठी <xliff:g id="TIME">%1$s</xliff:g> शिल्लक आहेत"</string> - <string name="power_charging_duration" msgid="6127154952524919719">"<xliff:g id="LEVEL">%1$s</xliff:g> - पूर्ण चार्ज होण्यासाठी <xliff:g id="TIME">%2$s</xliff:g> शिल्लक आहे"</string> - <string name="power_charging_limited" msgid="8202147604844938236">"<xliff:g id="LEVEL">%1$s</xliff:g> - चार्जिंग ऑप्टिमाइझ केले"</string> + <string name="power_charging_duration" msgid="6127154952524919719">"<xliff:g id="LEVEL">%1$s</xliff:g> - <xliff:g id="TIME">%2$s</xliff:g> या वेळेत बॅटरी पूर्ण चार्ज होईल"</string> + <!-- no translation found for power_charging_limited (4144004473976005214) --> + <skip /> <string name="power_charging_future_paused" msgid="1809543660923642799">"<xliff:g id="LEVEL">%1$s</xliff:g> ‑ चार्ज होत आहे"</string> <string name="power_fast_charging_duration_v2" msgid="3797735998640359490">"<xliff:g id="LEVEL">%1$s</xliff:g> - <xliff:g id="STATUS">%2$s</xliff:g> - <xliff:g id="TIME">%3$s</xliff:g> पर्यंत पूर्ण होईल"</string> <string name="power_charging_duration_v2" msgid="2938998284074003248">"<xliff:g id="LEVEL">%1$s</xliff:g> - <xliff:g id="TIME">%2$s</xliff:g> पर्यंत पूर्णपणे चार्ज होईल"</string> diff --git a/packages/SettingsLib/res/values-ms/strings.xml b/packages/SettingsLib/res/values-ms/strings.xml index 01d640998744..48ed79d8acfe 100644 --- a/packages/SettingsLib/res/values-ms/strings.xml +++ b/packages/SettingsLib/res/values-ms/strings.xml @@ -430,8 +430,7 @@ <string name="force_allow_on_external_summary" msgid="8525425782530728238">"Menjadikan sebarang apl layak ditulis ke storan luaran, tanpa mengambil kira nilai manifes"</string> <string name="force_resizable_activities" msgid="7143612144399959606">"Paksa aktiviti supaya boleh diubah saiz"</string> <string name="force_resizable_activities_summary" msgid="2490382056981583062">"Bolehkan semua saiz aktiviti diubah untuk berbilang tetingkap, tanpa mengambil kira nilai manifes."</string> - <string name="enable_freeform_support" msgid="8409932201445109106">"Dayakan tetingkap bentuk bebas (lama)"</string> - <string name="enable_freeform_support_summary" msgid="2242481082356957934">"Dayakan sokongan untuk tetingkap bentuk bebas lama yang bersifat percubaan."</string> + <string name="enable_freeform_support" msgid="7599125687603914253">"Dayakan tetingkap bentuk bebas"</string> <string name="local_backup_password_title" msgid="4631017948933578709">"Kata laluan sandaran desktop"</string> <string name="local_backup_password_summary_none" msgid="7646898032616361714">"Sandaran penuh desktop tidak dilindungi pada masa ini"</string> <string name="local_backup_password_summary_change" msgid="1707357670383995567">"Ketik untuk menukar atau mengalih keluar kata laluan untuk sandaran penuh desktop"</string> @@ -496,7 +495,8 @@ <string name="power_charging" msgid="6727132649743436802">"<xliff:g id="LEVEL">%1$s</xliff:g> - <xliff:g id="STATE">%2$s</xliff:g>"</string> <string name="power_remaining_charging_duration_only" msgid="8085099012811384899">"<xliff:g id="TIME">%1$s</xliff:g> lagi sebelum penuh"</string> <string name="power_charging_duration" msgid="6127154952524919719">"<xliff:g id="LEVEL">%1$s</xliff:g> - <xliff:g id="TIME">%2$s</xliff:g> lagi sebelum penuh"</string> - <string name="power_charging_limited" msgid="8202147604844938236">"<xliff:g id="LEVEL">%1$s</xliff:g> - Pengecasan dioptimumkan"</string> + <!-- no translation found for power_charging_limited (4144004473976005214) --> + <skip /> <string name="power_charging_future_paused" msgid="1809543660923642799">"<xliff:g id="LEVEL">%1$s</xliff:g> - Mengecas"</string> <string name="power_fast_charging_duration_v2" msgid="3797735998640359490">"<xliff:g id="LEVEL">%1$s</xliff:g> - <xliff:g id="STATUS">%2$s</xliff:g> - Penuh pada <xliff:g id="TIME">%3$s</xliff:g>"</string> <string name="power_charging_duration_v2" msgid="2938998284074003248">"<xliff:g id="LEVEL">%1$s</xliff:g> - Dicas sepenuhnya pada <xliff:g id="TIME">%2$s</xliff:g>"</string> diff --git a/packages/SettingsLib/res/values-my/strings.xml b/packages/SettingsLib/res/values-my/strings.xml index 92b630dc3422..d15a0be16545 100644 --- a/packages/SettingsLib/res/values-my/strings.xml +++ b/packages/SettingsLib/res/values-my/strings.xml @@ -430,8 +430,7 @@ <string name="force_allow_on_external_summary" msgid="8525425782530728238">"သတ်မှတ်တန်ဖိုးများ မည်သို့ပင်ရှိစေ ပြင်ပသိုလှောင်ခန်းများသို့ မည်သည့်အက်ပ်ကိုမဆို ဝင်ရောက်ခွင့်ပြုသည်"</string> <string name="force_resizable_activities" msgid="7143612144399959606">"လုပ်ဆောင်ချက်များ အရွယ်ပြောင်းနိုင်ခြင်း"</string> <string name="force_resizable_activities_summary" msgid="2490382056981583062">"သတ်မှတ်တန်ဖိုး မည်သို့ပင်ရှိစေ ဝင်းဒိုးများ၏ လုပ်ဆောင်မှုအားလုံးကို အရွယ်အစားပြင်သည်။"</string> - <string name="enable_freeform_support" msgid="8409932201445109106">"အလွတ်ပုံစံ ဝင်းဒိုးများ ဖွင့်ပါ (အဟောင်း)"</string> - <string name="enable_freeform_support_summary" msgid="2242481082356957934">"အလွတ်ပုံစံဝင်းဒိုးအဟောင်းများ စမ်းသပ်ရန် ပံ့ပိုးမှုရယူပါ။"</string> + <string name="enable_freeform_support" msgid="7599125687603914253">"ပုံစံမျိုးစုံ ဝင်းဒိုးများ ဖွင့်ရန်"</string> <string name="local_backup_password_title" msgid="4631017948933578709">"ဒက်စ်တော့ အရန်စကားဝှက်"</string> <string name="local_backup_password_summary_none" msgid="7646898032616361714">"ဒက်စ်တော့ တစ်ခုလုံး အရန်သိမ်းဆည်းခြင်းကို လက်ရှိတွင် ကာကွယ်မထားပါ"</string> <string name="local_backup_password_summary_change" msgid="1707357670383995567">"ဒက်စ်တော့ အပြည့်အဝ အရန်သိမ်းခြင်းအတွက် စကားဝှက်ကို ပြောင်းရန် သို့မဟုတ် ဖယ်ရှားရန် တို့ပါ။"</string> @@ -496,7 +495,8 @@ <string name="power_charging" msgid="6727132649743436802">"<xliff:g id="LEVEL">%1$s</xliff:g> - <xliff:g id="STATE">%2$s</xliff:g>"</string> <string name="power_remaining_charging_duration_only" msgid="8085099012811384899">"အားပြည့်ရန် <xliff:g id="TIME">%1$s</xliff:g> လိုသည်"</string> <string name="power_charging_duration" msgid="6127154952524919719">"<xliff:g id="LEVEL">%1$s</xliff:g> - အားပြည့်ရန် <xliff:g id="TIME">%2$s</xliff:g> လိုသည်"</string> - <string name="power_charging_limited" msgid="8202147604844938236">"<xliff:g id="LEVEL">%1$s</xliff:g> - အားသွင်းခြင်းကို အကောင်းဆုံးပြင်ဆင်ထားသည်"</string> + <!-- no translation found for power_charging_limited (4144004473976005214) --> + <skip /> <string name="power_charging_future_paused" msgid="1809543660923642799">"<xliff:g id="LEVEL">%1$s</xliff:g> - အားသွင်းနေသည်"</string> <string name="power_fast_charging_duration_v2" msgid="3797735998640359490">"<xliff:g id="LEVEL">%1$s</xliff:g> - <xliff:g id="STATUS">%2$s</xliff:g> - <xliff:g id="TIME">%3$s</xliff:g> တွင် အားပြည့်မည်"</string> <string name="power_charging_duration_v2" msgid="2938998284074003248">"<xliff:g id="LEVEL">%1$s</xliff:g> - <xliff:g id="TIME">%2$s</xliff:g> တွင် အားပြည့်မည်"</string> diff --git a/packages/SettingsLib/res/values-nb/strings.xml b/packages/SettingsLib/res/values-nb/strings.xml index 75b04ad04bf1..8f5663a1f7d2 100644 --- a/packages/SettingsLib/res/values-nb/strings.xml +++ b/packages/SettingsLib/res/values-nb/strings.xml @@ -430,8 +430,7 @@ <string name="force_allow_on_external_summary" msgid="8525425782530728238">"Dette gjør at alle apper kan lagres på eksterne lagringsmedier – uavhengig av manifestverdier"</string> <string name="force_resizable_activities" msgid="7143612144399959606">"Alle aktiviteter kan endre størrelse"</string> <string name="force_resizable_activities_summary" msgid="2490382056981583062">"Gjør at alle aktiviteter kan endre størrelse for flervindusmodus, uavhengig av manifestverdier."</string> - <string name="enable_freeform_support" msgid="8409932201445109106">"Slå på vinduer i fritt format (eldre versjon)"</string> - <string name="enable_freeform_support_summary" msgid="2242481082356957934">"Slå på støtte for eldre versjon av vinduer i eksperimentelt fritt format."</string> + <string name="enable_freeform_support" msgid="7599125687603914253">"Slå på vinduer i fritt format"</string> <string name="local_backup_password_title" msgid="4631017948933578709">"Passord for sikkerhetskopiering på datamaskin"</string> <string name="local_backup_password_summary_none" msgid="7646898032616361714">"Fullstendig sikkerhetskopiering på datamaskin er ikke beskyttet"</string> <string name="local_backup_password_summary_change" msgid="1707357670383995567">"Trykk for å endre eller fjerne passordet for fullstendige sikkerhetskopier på datamaskinen"</string> @@ -496,7 +495,8 @@ <string name="power_charging" msgid="6727132649743436802">"<xliff:g id="LEVEL">%1$s</xliff:g> – <xliff:g id="STATE">%2$s</xliff:g>"</string> <string name="power_remaining_charging_duration_only" msgid="8085099012811384899">"Fulladet om <xliff:g id="TIME">%1$s</xliff:g>"</string> <string name="power_charging_duration" msgid="6127154952524919719">"<xliff:g id="LEVEL">%1$s</xliff:g> – Fulladet om <xliff:g id="TIME">%2$s</xliff:g>"</string> - <string name="power_charging_limited" msgid="8202147604844938236">"<xliff:g id="LEVEL">%1$s</xliff:g> – Ladingen er optimalisert"</string> + <!-- no translation found for power_charging_limited (4144004473976005214) --> + <skip /> <string name="power_charging_future_paused" msgid="1809543660923642799">"<xliff:g id="LEVEL">%1$s</xliff:g> – lader"</string> <string name="power_fast_charging_duration_v2" msgid="3797735998640359490">"<xliff:g id="LEVEL">%1$s</xliff:g> – <xliff:g id="STATUS">%2$s</xliff:g> – Fulladet innen <xliff:g id="TIME">%3$s</xliff:g>"</string> <string name="power_charging_duration_v2" msgid="2938998284074003248">"<xliff:g id="LEVEL">%1$s</xliff:g> – Fulladet innen <xliff:g id="TIME">%2$s</xliff:g>"</string> diff --git a/packages/SettingsLib/res/values-ne/strings.xml b/packages/SettingsLib/res/values-ne/strings.xml index b25285486985..ddb58d5b2509 100644 --- a/packages/SettingsLib/res/values-ne/strings.xml +++ b/packages/SettingsLib/res/values-ne/strings.xml @@ -430,8 +430,7 @@ <string name="force_allow_on_external_summary" msgid="8525425782530728238">"तोकिएको नियमको ख्याल नगरी एपलाई बाह्य भण्डारणमा चल्ने बनाउनुहोस्"</string> <string name="force_resizable_activities" msgid="7143612144399959606">"बलपूर्वक एपहरूको आकार मिलाउन मिल्ने बनाउनुहोस्"</string> <string name="force_resizable_activities_summary" msgid="2490382056981583062">"तोकिएको नियमको ख्याल नगरी एपलाई एकभन्दा बढी विन्डोमा रिसाइज गर्न सकिने बनाउनुहोस्।"</string> - <string name="enable_freeform_support" msgid="8409932201445109106">"फ्रिफर्म विन्डोहरू अन गर्नुहोस् (लिगेसी)"</string> - <string name="enable_freeform_support_summary" msgid="2242481082356957934">"प्रयोगात्मक लिगेसी फ्रिफर्म विन्डोहरू चल्ने बनाउनुहोस्"</string> + <string name="enable_freeform_support" msgid="7599125687603914253">"फ्रिफर्म विन्डोहरू अन गर्नुहोस्"</string> <string name="local_backup_password_title" msgid="4631017948933578709">"डेस्कटप ब्याकअप पासवर्ड"</string> <string name="local_backup_password_summary_none" msgid="7646898032616361714">"हाल डेस्कटपका सबै ब्याकअप पासवर्ड सुरक्षित छैनन्"</string> <string name="local_backup_password_summary_change" msgid="1707357670383995567">"डेस्कटप पूर्ण ब्याकअपको लागि पासवर्ड बदल्न वा हटाउन ट्याप गर्नुहोस्"</string> @@ -496,7 +495,8 @@ <string name="power_charging" msgid="6727132649743436802">"<xliff:g id="LEVEL">%1$s</xliff:g> - <xliff:g id="STATE">%2$s</xliff:g>"</string> <string name="power_remaining_charging_duration_only" msgid="8085099012811384899">"पूरा चार्ज हुन <xliff:g id="TIME">%1$s</xliff:g> लाग्ने छ"</string> <string name="power_charging_duration" msgid="6127154952524919719">"<xliff:g id="LEVEL">%1$s</xliff:g> - पूरा चार्ज हुन <xliff:g id="TIME">%2$s</xliff:g> लाग्ने छ"</string> - <string name="power_charging_limited" msgid="8202147604844938236">"<xliff:g id="LEVEL">%1$s</xliff:g> - चार्ज गर्ने प्रक्रिया अप्टिमाइज गरिएको छ"</string> + <!-- no translation found for power_charging_limited (4144004473976005214) --> + <skip /> <string name="power_charging_future_paused" msgid="1809543660923642799">"<xliff:g id="LEVEL">%1$s</xliff:g> - चार्ज गरिँदै छ"</string> <string name="power_fast_charging_duration_v2" msgid="3797735998640359490">"<xliff:g id="LEVEL">%1$s</xliff:g> - <xliff:g id="STATUS">%2$s</xliff:g> - <xliff:g id="TIME">%3$s</xliff:g> बजेसम्ममा पूरा चार्ज हुने छ"</string> <string name="power_charging_duration_v2" msgid="2938998284074003248">"<xliff:g id="LEVEL">%1$s</xliff:g> - <xliff:g id="TIME">%2$s</xliff:g> बजेसम्ममा पूरा चार्ज हुने छ"</string> diff --git a/packages/SettingsLib/res/values-nl/strings.xml b/packages/SettingsLib/res/values-nl/strings.xml index 8577f4853b23..abf00f0a5f41 100644 --- a/packages/SettingsLib/res/values-nl/strings.xml +++ b/packages/SettingsLib/res/values-nl/strings.xml @@ -430,8 +430,7 @@ <string name="force_allow_on_external_summary" msgid="8525425782530728238">"Hiermee komt elke app in aanmerking voor schrijven naar externe opslag, ongeacht de manifestwaarden"</string> <string name="force_resizable_activities" msgid="7143612144399959606">"Formaat activiteiten geforceerd aanpasbaar maken"</string> <string name="force_resizable_activities_summary" msgid="2490382056981583062">"Maak het formaat van alle activiteiten aanpasbaar, ongeacht de manifestwaarden"</string> - <string name="enable_freeform_support" msgid="8409932201445109106">"Vensters met vrije vorm aanzetten (verouderd)"</string> - <string name="enable_freeform_support_summary" msgid="2242481082356957934">"Zet ondersteuning voor verouderde vensters met experimentele vrije vorm aan."</string> + <string name="enable_freeform_support" msgid="7599125687603914253">"Vensters met vrije vorm aanzetten"</string> <string name="local_backup_password_title" msgid="4631017948933578709">"Wachtwoord desktopback-up"</string> <string name="local_backup_password_summary_none" msgid="7646898032616361714">"Volledige back-ups naar desktops zijn momenteel niet beveiligd"</string> <string name="local_backup_password_summary_change" msgid="1707357670383995567">"Tik om het wachtwoord voor volledige back-ups naar desktops te wijzigen of te verwijderen"</string> @@ -496,7 +495,8 @@ <string name="power_charging" msgid="6727132649743436802">"<xliff:g id="LEVEL">%1$s</xliff:g> - <xliff:g id="STATE">%2$s</xliff:g>"</string> <string name="power_remaining_charging_duration_only" msgid="8085099012811384899">"Vol over <xliff:g id="TIME">%1$s</xliff:g>"</string> <string name="power_charging_duration" msgid="6127154952524919719">"<xliff:g id="LEVEL">%1$s</xliff:g> - vol over <xliff:g id="TIME">%2$s</xliff:g>"</string> - <string name="power_charging_limited" msgid="8202147604844938236">"<xliff:g id="LEVEL">%1$s</xliff:g> - Opladen geoptimaliseerd"</string> + <!-- no translation found for power_charging_limited (4144004473976005214) --> + <skip /> <string name="power_charging_future_paused" msgid="1809543660923642799">"<xliff:g id="LEVEL">%1$s</xliff:g> ‑ Opladen"</string> <string name="power_fast_charging_duration_v2" msgid="3797735998640359490">"<xliff:g id="LEVEL">%1$s</xliff:g> - <xliff:g id="STATUS">%2$s</xliff:g> - Vol om <xliff:g id="TIME">%3$s</xliff:g>"</string> <string name="power_charging_duration_v2" msgid="2938998284074003248">"<xliff:g id="LEVEL">%1$s</xliff:g> - Volledig opgeladen om <xliff:g id="TIME">%2$s</xliff:g>"</string> diff --git a/packages/SettingsLib/res/values-or/strings.xml b/packages/SettingsLib/res/values-or/strings.xml index 9fdb99b64bb7..941a627f5215 100644 --- a/packages/SettingsLib/res/values-or/strings.xml +++ b/packages/SettingsLib/res/values-or/strings.xml @@ -430,8 +430,7 @@ <string name="force_allow_on_external_summary" msgid="8525425782530728238">"ଯେକୌଣସି ଆପ୍କୁ ଏକ୍ସଟର୍ନଲ୍ ଷ୍ଟୋରେଜ୍ରେ ଲେଖାଯୋଗ୍ୟ କରନ୍ତୁ, ମେନିଫେଷ୍ଟ ମୂଲ୍ୟ ଯାହା ହୋଇଥାଉ ନା କାହିଁକି"</string> <string name="force_resizable_activities" msgid="7143612144399959606">"ୱିଣ୍ଡୋ ହିସାବରେ କାର୍ଯ୍ୟକଳାପର ଆକାର ବଦଳାନ୍ତୁ"</string> <string name="force_resizable_activities_summary" msgid="2490382056981583062">"ମାନିଫେଷ୍ଟ ମୂଲ୍ୟ ଯାହା ହୋଇଥାଉ ନା କାହିଁକି, ଏକାଧିକ-ୱିଣ୍ଡୋ ପାଇଁ ସମସ୍ତ କାର୍ଯ୍ୟକଳାପକୁ ରିସାଇଜ କରନ୍ତୁ।"</string> - <string name="enable_freeform_support" msgid="8409932201445109106">"ଫ୍ରିଫର୍ମ ୱିଣ୍ଡୋ ସକ୍ଷମ କରନ୍ତୁ (ଲିଗାସି)"</string> - <string name="enable_freeform_support_summary" msgid="2242481082356957934">"ପରୀକ୍ଷାମୂଳକ ଲିଗାସି ଫ୍ରିଫର୍ମ ୱିଣ୍ଡୋ ପାଇଁ ସପୋର୍ଟ ସକ୍ଷମ କରନ୍ତୁ।"</string> + <string name="enable_freeform_support" msgid="7599125687603914253">"ଫ୍ରିଫର୍ମ ୱିଣ୍ଡୋକୁ ସକ୍ଷମ କରନ୍ତୁ"</string> <string name="local_backup_password_title" msgid="4631017948933578709">"ଡେସ୍କଟପ ବେକଅପ ପାସୱାର୍ଡ"</string> <string name="local_backup_password_summary_none" msgid="7646898032616361714">"ଡେସ୍କଟପ୍ର ସମ୍ପୂର୍ଣ୍ଣ ବ୍ୟାକଅପ୍ଗୁଡ଼ିକ ବର୍ତ୍ତମାନ ସୁରକ୍ଷିତ ନୁହେଁ"</string> <string name="local_backup_password_summary_change" msgid="1707357670383995567">"ଡେସ୍କଟପ୍ର ସମ୍ପୂର୍ଣ୍ଣ ବ୍ୟାକ୍ଅପ୍ ପାଇଁ ପାସ୍ୱର୍ଡ ବଦଳାଇବା କିମ୍ୱା କାଢ଼ିଦେବା ନିମନ୍ତେ ଟାପ୍ କରନ୍ତୁ"</string> @@ -496,7 +495,8 @@ <string name="power_charging" msgid="6727132649743436802">"<xliff:g id="LEVEL">%1$s</xliff:g> - <xliff:g id="STATE">%2$s</xliff:g>"</string> <string name="power_remaining_charging_duration_only" msgid="8085099012811384899">"ପୂର୍ଣ୍ଣ ହେବାକୁ ଆଉ <xliff:g id="TIME">%1$s</xliff:g> ବାକି ଅଛି"</string> <string name="power_charging_duration" msgid="6127154952524919719">"<xliff:g id="LEVEL">%1$s</xliff:g> - ପୂର୍ଣ୍ଣ ହେବାକୁ ଆଉ <xliff:g id="TIME">%2$s</xliff:g> ବାକି ଅଛି"</string> - <string name="power_charging_limited" msgid="8202147604844938236">"<xliff:g id="LEVEL">%1$s</xliff:g> - ଚାର୍ଜିଂକୁ ଅପ୍ଟିମାଇଜ କରାଯାଇଛି"</string> + <!-- no translation found for power_charging_limited (4144004473976005214) --> + <skip /> <string name="power_charging_future_paused" msgid="1809543660923642799">"<xliff:g id="LEVEL">%1$s</xliff:g> ‑ ଚାର୍ଜିଂ"</string> <string name="power_fast_charging_duration_v2" msgid="3797735998640359490">"<xliff:g id="LEVEL">%1$s</xliff:g> - <xliff:g id="STATUS">%2$s</xliff:g> - <xliff:g id="TIME">%3$s</xliff:g> ସୁଦ୍ଧା ସମ୍ପୂର୍ଣ୍ଣ ଚାର୍ଜ ହେବ"</string> <string name="power_charging_duration_v2" msgid="2938998284074003248">"<xliff:g id="LEVEL">%1$s</xliff:g> • <xliff:g id="TIME">%2$s</xliff:g> ସୁଦ୍ଧା ସମ୍ପୂର୍ଣ୍ଣ ଭାବେ ଚାର୍ଜ ହୋଇଯିବ"</string> diff --git a/packages/SettingsLib/res/values-pa/strings.xml b/packages/SettingsLib/res/values-pa/strings.xml index 64981a7a1dec..09fd778a617b 100644 --- a/packages/SettingsLib/res/values-pa/strings.xml +++ b/packages/SettingsLib/res/values-pa/strings.xml @@ -430,8 +430,7 @@ <string name="force_allow_on_external_summary" msgid="8525425782530728238">"ਮੈਨੀਫੈਸਟ ਮੁੱਲਾਂ ਦੀ ਪਰਵਾਹ ਕੀਤੇ ਬਿਨਾਂ, ਕਿਸੇ ਵੀ ਐਪ ਨੂੰ ਬਾਹਰੀ ਸਟੋਰੇਜ \'ਤੇ ਲਿਖਣ ਦੇ ਯੋਗ ਬਣਾਉਂਦੀ ਹੈ"</string> <string name="force_resizable_activities" msgid="7143612144399959606">"ਸਰਗਰਮੀਆਂ ਨੂੰ ਜ਼ਬਰਦਸਤੀ ਆਕਾਰ ਬਦਲਣਯੋਗ ਬਣਾਓ"</string> <string name="force_resizable_activities_summary" msgid="2490382056981583062">"ਮੈਨੀਫ਼ੈਸਟ ਮੁੱਲਾਂ ਦੀ ਪਰਵਾਹ ਕੀਤੇ ਬਿਨਾਂ, ਮਲਟੀ-ਵਿੰਡੋ ਲਈ ਸਾਰੀਆਂ ਸਰਗਰਮੀਆਂ ਨੂੰ ਆਕਾਰ ਬਦਲਣਯੋਗ ਬਣਾਓ।"</string> - <string name="enable_freeform_support" msgid="8409932201445109106">"ਫ੍ਰੀਫਾਰਮ ਵਿੰਡੋਆਂ ਚਾਲੂ ਕਰੋ (ਵਿਰਾਸਤੀ)"</string> - <string name="enable_freeform_support_summary" msgid="2242481082356957934">"ਪ੍ਰਯੋਗਮਈ ਵਿਰਾਸਤੀ ਫ੍ਰੀਫਾਰਮ ਵਿੰਡੋਆਂ ਲਈ ਸਹਾਇਤਾ ਚਾਲੂ ਕਰੋ।"</string> + <string name="enable_freeform_support" msgid="7599125687603914253">"ਫ੍ਰੀਫਾਰਮ ਵਿੰਡੋਜ਼ ਨੂੰ ਚਾਲੂ ਕਰੋ"</string> <string name="local_backup_password_title" msgid="4631017948933578709">"ਡੈਸਕਟਾਪ ਬੈਕਅੱਪ ਪਾਸਵਰਡ"</string> <string name="local_backup_password_summary_none" msgid="7646898032616361714">"ਡੈਸਕਟਾਪ ਦੇ ਪੂਰੇ ਬੈਕਅੱਪ ਇਸ ਵੇਲੇ ਸੁਰੱਖਿਅਤ ਨਹੀਂ ਹਨ"</string> <string name="local_backup_password_summary_change" msgid="1707357670383995567">"ਡੈਸਕਟਾਪ ਦੇ ਮੁਕੰਮਲ ਬੈਕਅੱਪਾਂ ਲਈ ਪਾਸਵਰਡ ਨੂੰ ਬਦਲਣ ਜਾਂ ਹਟਾਉਣ ਲਈ ਟੈਪ ਕਰੋ"</string> @@ -496,7 +495,8 @@ <string name="power_charging" msgid="6727132649743436802">"<xliff:g id="LEVEL">%1$s</xliff:g> - <xliff:g id="STATE">%2$s</xliff:g>"</string> <string name="power_remaining_charging_duration_only" msgid="8085099012811384899">"ਬੈਟਰੀ ਪੂਰੀ ਚਾਰਜ ਹੋਣ ਵਿੱਚ <xliff:g id="TIME">%1$s</xliff:g> ਬਾਕੀ"</string> <string name="power_charging_duration" msgid="6127154952524919719">"<xliff:g id="LEVEL">%1$s</xliff:g> - ਬੈਟਰੀ ਪੂਰੀ ਚਾਰਜ ਹੋਣ ਵਿੱਚ <xliff:g id="TIME">%2$s</xliff:g> ਬਾਕੀ"</string> - <string name="power_charging_limited" msgid="8202147604844938236">"<xliff:g id="LEVEL">%1$s</xliff:g> - ਚਾਰਜਿੰਗ ਨੂੰ ਸੁਯੋਗ ਬਣਾਇਆ ਗਿਆ"</string> + <!-- no translation found for power_charging_limited (4144004473976005214) --> + <skip /> <string name="power_charging_future_paused" msgid="1809543660923642799">"<xliff:g id="LEVEL">%1$s</xliff:g> - ਚਾਰਜ ਹੋ ਰਹੀ ਹੈ"</string> <string name="power_fast_charging_duration_v2" msgid="3797735998640359490">"<xliff:g id="LEVEL">%1$s</xliff:g> - <xliff:g id="STATUS">%2$s</xliff:g> - <xliff:g id="TIME">%3$s</xliff:g> ਤੱਕ ਪੂਰੀ ਤਰ੍ਹਾਂ ਚਾਰਜ ਹੋ ਜਾਵੇਗੀ"</string> <string name="power_charging_duration_v2" msgid="2938998284074003248">"<xliff:g id="LEVEL">%1$s</xliff:g> - <xliff:g id="TIME">%2$s</xliff:g> ਤੱਕ ਪੂਰੀ ਤਰ੍ਹਾਂ ਚਾਰਜ ਹੋ ਜਾਵੇਗੀ"</string> diff --git a/packages/SettingsLib/res/values-pl/strings.xml b/packages/SettingsLib/res/values-pl/strings.xml index a1ca4a6b8fcd..7840cb0b18e7 100644 --- a/packages/SettingsLib/res/values-pl/strings.xml +++ b/packages/SettingsLib/res/values-pl/strings.xml @@ -430,8 +430,7 @@ <string name="force_allow_on_external_summary" msgid="8525425782530728238">"Pozwala na zapis aplikacji w pamięci zewnętrznej niezależnie od wartości w pliku manifestu"</string> <string name="force_resizable_activities" msgid="7143612144399959606">"Wymuś zmianę rozmiaru okien aktywności"</string> <string name="force_resizable_activities_summary" msgid="2490382056981583062">"Zezwalaj na zmianę rozmiaru wszystkich okien aktywności w trybie wielu okien niezależnie od ustawień w pliku manifestu"</string> - <string name="enable_freeform_support" msgid="8409932201445109106">"Włącz dowolny rozmiar okien (starsza wersja)"</string> - <string name="enable_freeform_support_summary" msgid="2242481082356957934">"Włącz obsługę eksperymentalnej funkcji dowolnego rozmiaru okien w starszej wersji"</string> + <string name="enable_freeform_support" msgid="7599125687603914253">"Włącz dowolny rozmiar okien"</string> <string name="local_backup_password_title" msgid="4631017948933578709">"Hasło kopii zapasowej"</string> <string name="local_backup_password_summary_none" msgid="7646898032616361714">"Pełne kopie zapasowe na komputerze nie są obecnie chronione"</string> <string name="local_backup_password_summary_change" msgid="1707357670383995567">"Dotknij, by zmienić lub usunąć hasło pełnych kopii zapasowych na komputerze."</string> @@ -496,7 +495,8 @@ <string name="power_charging" msgid="6727132649743436802">"<xliff:g id="LEVEL">%1$s</xliff:g> – <xliff:g id="STATE">%2$s</xliff:g>"</string> <string name="power_remaining_charging_duration_only" msgid="8085099012811384899">"<xliff:g id="TIME">%1$s</xliff:g> do pełnego naładowania"</string> <string name="power_charging_duration" msgid="6127154952524919719">"<xliff:g id="LEVEL">%1$s</xliff:g> – <xliff:g id="TIME">%2$s</xliff:g> do pełnego naładowania"</string> - <string name="power_charging_limited" msgid="8202147604844938236">"<xliff:g id="LEVEL">%1$s</xliff:g> – ładowanie zoptymalizowane"</string> + <!-- no translation found for power_charging_limited (4144004473976005214) --> + <skip /> <string name="power_charging_future_paused" msgid="1809543660923642799">"<xliff:g id="LEVEL">%1$s</xliff:g> – ładowanie"</string> <string name="power_fast_charging_duration_v2" msgid="3797735998640359490">"<xliff:g id="LEVEL">%1$s</xliff:g> – <xliff:g id="STATUS">%2$s</xliff:g> – Bateria będzie pełna do <xliff:g id="TIME">%3$s</xliff:g>"</string> <string name="power_charging_duration_v2" msgid="2938998284074003248">"<xliff:g id="LEVEL">%1$s</xliff:g> – Pełne naładowanie do <xliff:g id="TIME">%2$s</xliff:g>"</string> diff --git a/packages/SettingsLib/res/values-pt-rBR/strings.xml b/packages/SettingsLib/res/values-pt-rBR/strings.xml index 13f9c40f329b..9209d627778a 100644 --- a/packages/SettingsLib/res/values-pt-rBR/strings.xml +++ b/packages/SettingsLib/res/values-pt-rBR/strings.xml @@ -430,8 +430,7 @@ <string name="force_allow_on_external_summary" msgid="8525425782530728238">"Qualificar apps para gravação em armazenamento externo, independentemente dos valores do manifesto"</string> <string name="force_resizable_activities" msgid="7143612144399959606">"Forçar atividades a serem redimensionáveis"</string> <string name="force_resizable_activities_summary" msgid="2490382056981583062">"Tornar todas as atividades redimensionáveis para várias janelas, independentemente dos valores do manifesto"</string> - <string name="enable_freeform_support" msgid="8409932201445109106">"Ativar janelas de forma livre (legado)"</string> - <string name="enable_freeform_support_summary" msgid="2242481082356957934">"Ativar a compatibilidade com janelas experimentais legadas de forma livre."</string> + <string name="enable_freeform_support" msgid="7599125687603914253">"Ativar janelas de forma livre"</string> <string name="local_backup_password_title" msgid="4631017948933578709">"Senha de backup local"</string> <string name="local_backup_password_summary_none" msgid="7646898032616361714">"Os backups completos não estão protegidos no momento"</string> <string name="local_backup_password_summary_change" msgid="1707357670383995567">"Toque para alterar ou remover a senha de backups completos do desktop"</string> @@ -496,7 +495,8 @@ <string name="power_charging" msgid="6727132649743436802">"<xliff:g id="LEVEL">%1$s</xliff:g> - <xliff:g id="STATE">%2$s</xliff:g>"</string> <string name="power_remaining_charging_duration_only" msgid="8085099012811384899">"<xliff:g id="TIME">%1$s</xliff:g> até a conclusão"</string> <string name="power_charging_duration" msgid="6127154952524919719">"<xliff:g id="LEVEL">%1$s</xliff:g>: <xliff:g id="TIME">%2$s</xliff:g> até a conclusão"</string> - <string name="power_charging_limited" msgid="8202147604844938236">"<xliff:g id="LEVEL">%1$s</xliff:g> - Carregamento otimizado"</string> + <!-- no translation found for power_charging_limited (4144004473976005214) --> + <skip /> <string name="power_charging_future_paused" msgid="1809543660923642799">"<xliff:g id="LEVEL">%1$s</xliff:g> (carregando)"</string> <string name="power_fast_charging_duration_v2" msgid="3797735998640359490">"<xliff:g id="LEVEL">%1$s</xliff:g> - <xliff:g id="STATUS">%2$s</xliff:g> - Carregado até <xliff:g id="TIME">%3$s</xliff:g>"</string> <string name="power_charging_duration_v2" msgid="2938998284074003248">"<xliff:g id="LEVEL">%1$s</xliff:g> - Totalmente carregado até <xliff:g id="TIME">%2$s</xliff:g>"</string> diff --git a/packages/SettingsLib/res/values-pt-rPT/strings.xml b/packages/SettingsLib/res/values-pt-rPT/strings.xml index 260e58e0b365..2cd6811324e0 100644 --- a/packages/SettingsLib/res/values-pt-rPT/strings.xml +++ b/packages/SettingsLib/res/values-pt-rPT/strings.xml @@ -430,8 +430,7 @@ <string name="force_allow_on_external_summary" msgid="8525425782530728238">"Torna qualquer aplicação elegível para ser gravada no armazenamento externo, independentemente dos valores do manifesto"</string> <string name="force_resizable_activities" msgid="7143612144399959606">"Forçar as atividades a serem redimensionáveis"</string> <string name="force_resizable_activities_summary" msgid="2490382056981583062">"Tornar todas as atividades redimensionáveis para várias janelas, independentemente dos valores do manifesto."</string> - <string name="enable_freeform_support" msgid="8409932201445109106">"Ativar janelas de forma livre (antigo)"</string> - <string name="enable_freeform_support_summary" msgid="2242481082356957934">"Ativar compatibilidade com janelas de forma livre antigas experimentais."</string> + <string name="enable_freeform_support" msgid="7599125687603914253">"Ativar janelas de forma livre"</string> <string name="local_backup_password_title" msgid="4631017948933578709">"Palavra-passe cópia do computador"</string> <string name="local_backup_password_summary_none" msgid="7646898032616361714">"As cópias de segurança completas no ambiente de trabalho não estão atualmente protegidas"</string> <string name="local_backup_password_summary_change" msgid="1707357670383995567">"Tocar para alterar ou remover a palavra-passe para cópias de segurança completas no ambiente de trabalho"</string> @@ -496,7 +495,8 @@ <string name="power_charging" msgid="6727132649743436802">"<xliff:g id="LEVEL">%1$s</xliff:g> – <xliff:g id="STATE">%2$s</xliff:g>"</string> <string name="power_remaining_charging_duration_only" msgid="8085099012811384899">"<xliff:g id="TIME">%1$s</xliff:g> até à carga máxima"</string> <string name="power_charging_duration" msgid="6127154952524919719">"<xliff:g id="LEVEL">%1$s</xliff:g> – <xliff:g id="TIME">%2$s</xliff:g> até à carga máxima"</string> - <string name="power_charging_limited" msgid="8202147604844938236">"<xliff:g id="LEVEL">%1$s</xliff:g>: carregamento otimizado"</string> + <!-- no translation found for power_charging_limited (4144004473976005214) --> + <skip /> <string name="power_charging_future_paused" msgid="1809543660923642799">"<xliff:g id="LEVEL">%1$s</xliff:g> – A carregar"</string> <string name="power_fast_charging_duration_v2" msgid="3797735998640359490">"<xliff:g id="LEVEL">%1$s</xliff:g> – <xliff:g id="STATUS">%2$s</xliff:g> – Completo à(s) <xliff:g id="TIME">%3$s</xliff:g>"</string> <string name="power_charging_duration_v2" msgid="2938998284074003248">"<xliff:g id="LEVEL">%1$s</xliff:g> – Completamente carregado à(s) <xliff:g id="TIME">%2$s</xliff:g>"</string> diff --git a/packages/SettingsLib/res/values-pt/strings.xml b/packages/SettingsLib/res/values-pt/strings.xml index 13f9c40f329b..9209d627778a 100644 --- a/packages/SettingsLib/res/values-pt/strings.xml +++ b/packages/SettingsLib/res/values-pt/strings.xml @@ -430,8 +430,7 @@ <string name="force_allow_on_external_summary" msgid="8525425782530728238">"Qualificar apps para gravação em armazenamento externo, independentemente dos valores do manifesto"</string> <string name="force_resizable_activities" msgid="7143612144399959606">"Forçar atividades a serem redimensionáveis"</string> <string name="force_resizable_activities_summary" msgid="2490382056981583062">"Tornar todas as atividades redimensionáveis para várias janelas, independentemente dos valores do manifesto"</string> - <string name="enable_freeform_support" msgid="8409932201445109106">"Ativar janelas de forma livre (legado)"</string> - <string name="enable_freeform_support_summary" msgid="2242481082356957934">"Ativar a compatibilidade com janelas experimentais legadas de forma livre."</string> + <string name="enable_freeform_support" msgid="7599125687603914253">"Ativar janelas de forma livre"</string> <string name="local_backup_password_title" msgid="4631017948933578709">"Senha de backup local"</string> <string name="local_backup_password_summary_none" msgid="7646898032616361714">"Os backups completos não estão protegidos no momento"</string> <string name="local_backup_password_summary_change" msgid="1707357670383995567">"Toque para alterar ou remover a senha de backups completos do desktop"</string> @@ -496,7 +495,8 @@ <string name="power_charging" msgid="6727132649743436802">"<xliff:g id="LEVEL">%1$s</xliff:g> - <xliff:g id="STATE">%2$s</xliff:g>"</string> <string name="power_remaining_charging_duration_only" msgid="8085099012811384899">"<xliff:g id="TIME">%1$s</xliff:g> até a conclusão"</string> <string name="power_charging_duration" msgid="6127154952524919719">"<xliff:g id="LEVEL">%1$s</xliff:g>: <xliff:g id="TIME">%2$s</xliff:g> até a conclusão"</string> - <string name="power_charging_limited" msgid="8202147604844938236">"<xliff:g id="LEVEL">%1$s</xliff:g> - Carregamento otimizado"</string> + <!-- no translation found for power_charging_limited (4144004473976005214) --> + <skip /> <string name="power_charging_future_paused" msgid="1809543660923642799">"<xliff:g id="LEVEL">%1$s</xliff:g> (carregando)"</string> <string name="power_fast_charging_duration_v2" msgid="3797735998640359490">"<xliff:g id="LEVEL">%1$s</xliff:g> - <xliff:g id="STATUS">%2$s</xliff:g> - Carregado até <xliff:g id="TIME">%3$s</xliff:g>"</string> <string name="power_charging_duration_v2" msgid="2938998284074003248">"<xliff:g id="LEVEL">%1$s</xliff:g> - Totalmente carregado até <xliff:g id="TIME">%2$s</xliff:g>"</string> diff --git a/packages/SettingsLib/res/values-ro/strings.xml b/packages/SettingsLib/res/values-ro/strings.xml index 5f8f367e109b..e33c02f7b3c5 100644 --- a/packages/SettingsLib/res/values-ro/strings.xml +++ b/packages/SettingsLib/res/values-ro/strings.xml @@ -430,8 +430,7 @@ <string name="force_allow_on_external_summary" msgid="8525425782530728238">"Permite scrierea oricărei aplicații eligibile în stocarea externă, indiferent de valorile manifestului"</string> <string name="force_resizable_activities" msgid="7143612144399959606">"Forțează redimensionarea activităților"</string> <string name="force_resizable_activities_summary" msgid="2490382056981583062">"Permite redimensionarea tuturor activităților pentru modul cu ferestre multiple, indiferent de valorile manifestului."</string> - <string name="enable_freeform_support" msgid="8409932201445109106">"Activează ferestrele cu formă liberă (vechi)"</string> - <string name="enable_freeform_support_summary" msgid="2242481082356957934">"Activează compatibilitatea pentru ferestrele experimentale vechi cu formă liberă."</string> + <string name="enable_freeform_support" msgid="7599125687603914253">"Activează ferestrele cu formă liberă"</string> <string name="local_backup_password_title" msgid="4631017948933578709">"Parolă backup computer"</string> <string name="local_backup_password_summary_none" msgid="7646898032616361714">"În prezent, backupurile complete pe computer nu sunt protejate"</string> <string name="local_backup_password_summary_change" msgid="1707357670383995567">"Atinge ca să modifici sau să elimini parola pentru backupurile complete pe desktop"</string> @@ -496,7 +495,8 @@ <string name="power_charging" msgid="6727132649743436802">"<xliff:g id="LEVEL">%1$s</xliff:g> - <xliff:g id="STATE">%2$s</xliff:g>"</string> <string name="power_remaining_charging_duration_only" msgid="8085099012811384899">"<xliff:g id="TIME">%1$s</xliff:g> până la finalizare"</string> <string name="power_charging_duration" msgid="6127154952524919719">"<xliff:g id="LEVEL">%1$s</xliff:g> – <xliff:g id="TIME">%2$s</xliff:g> până la finalizare"</string> - <string name="power_charging_limited" msgid="8202147604844938236">"<xliff:g id="LEVEL">%1$s</xliff:g> – Încărcare optimizată"</string> + <!-- no translation found for power_charging_limited (4144004473976005214) --> + <skip /> <string name="power_charging_future_paused" msgid="1809543660923642799">"<xliff:g id="LEVEL">%1$s</xliff:g> – Se încarcă"</string> <string name="power_fast_charging_duration_v2" msgid="3797735998640359490">"<xliff:g id="LEVEL">%1$s</xliff:g> - <xliff:g id="STATUS">%2$s</xliff:g> - Timp rămas <xliff:g id="TIME">%3$s</xliff:g>"</string> <string name="power_charging_duration_v2" msgid="2938998284074003248">"<xliff:g id="LEVEL">%1$s</xliff:g> - Complet încărcat în <xliff:g id="TIME">%2$s</xliff:g>"</string> diff --git a/packages/SettingsLib/res/values-ru/strings.xml b/packages/SettingsLib/res/values-ru/strings.xml index f492b65612c5..4de495a9c9ff 100644 --- a/packages/SettingsLib/res/values-ru/strings.xml +++ b/packages/SettingsLib/res/values-ru/strings.xml @@ -430,8 +430,7 @@ <string name="force_allow_on_external_summary" msgid="8525425782530728238">"Разрешить сохранение приложений на внешних накопителях (независимо от значений в манифесте)"</string> <string name="force_resizable_activities" msgid="7143612144399959606">"Изменение размера в многооконном режиме"</string> <string name="force_resizable_activities_summary" msgid="2490382056981583062">"Разрешить изменение размера окон в многооконном режиме (независимо от значений в манифесте)"</string> - <string name="enable_freeform_support" msgid="8409932201445109106">"Разрешить окна произвольной формы (устаревшее)"</string> - <string name="enable_freeform_support_summary" msgid="2242481082356957934">"Включить устаревшую экспериментальную функцию для создания окон произвольной формы"</string> + <string name="enable_freeform_support" msgid="7599125687603914253">"Разрешить создание окон произвольной формы"</string> <string name="local_backup_password_title" msgid="4631017948933578709">"Пароль для резервного копирования"</string> <string name="local_backup_password_summary_none" msgid="7646898032616361714">"Полные локальные резервные копии в настоящее время не защищены"</string> <string name="local_backup_password_summary_change" msgid="1707357670383995567">"Нажмите, чтобы изменить или удалить пароль для резервного копирования"</string> @@ -496,7 +495,8 @@ <string name="power_charging" msgid="6727132649743436802">"<xliff:g id="LEVEL">%1$s</xliff:g> – <xliff:g id="STATE">%2$s</xliff:g>"</string> <string name="power_remaining_charging_duration_only" msgid="8085099012811384899">"<xliff:g id="TIME">%1$s</xliff:g> до полной зарядки"</string> <string name="power_charging_duration" msgid="6127154952524919719">"<xliff:g id="LEVEL">%1$s</xliff:g> – <xliff:g id="TIME">%2$s</xliff:g> до полной зарядки"</string> - <string name="power_charging_limited" msgid="8202147604844938236">"<xliff:g id="LEVEL">%1$s</xliff:g> – зарядка оптимизирована"</string> + <!-- no translation found for power_charging_limited (4144004473976005214) --> + <skip /> <string name="power_charging_future_paused" msgid="1809543660923642799">"<xliff:g id="LEVEL">%1$s</xliff:g> – заряжается"</string> <string name="power_fast_charging_duration_v2" msgid="3797735998640359490">"<xliff:g id="LEVEL">%1$s</xliff:g>. <xliff:g id="STATUS">%2$s</xliff:g> – завершится к <xliff:g id="TIME">%3$s</xliff:g>."</string> <string name="power_charging_duration_v2" msgid="2938998284074003248">"<xliff:g id="LEVEL">%1$s</xliff:g> – полностью зарядится к <xliff:g id="TIME">%2$s</xliff:g>"</string> diff --git a/packages/SettingsLib/res/values-si/strings.xml b/packages/SettingsLib/res/values-si/strings.xml index 42cde8b7cc2c..9a4ca8eb2a26 100644 --- a/packages/SettingsLib/res/values-si/strings.xml +++ b/packages/SettingsLib/res/values-si/strings.xml @@ -430,8 +430,7 @@ <string name="force_allow_on_external_summary" msgid="8525425782530728238">"මැනිෆෙස්ට් අගයන් නොසලකා, ඕනෑම යෙදුමක් බාහිර ගබඩාවට ලිවීමට සුදුසුකම් ලබා දෙයි"</string> <string name="force_resizable_activities" msgid="7143612144399959606">"ක්රියාකාරකම් ප්රතිප්රමාණ කළ හැකි බවට බල කරන්න"</string> <string name="force_resizable_activities_summary" msgid="2490382056981583062">"මැනිෆෙස්ට් අගයන් නොසලකා, සියලු ක්රියාකාරකම් බහු-කවුළුව සඳහා ප්රතිප්රමාණ කළ හැකි බවට පත් කරන්න."</string> - <string name="enable_freeform_support" msgid="8409932201445109106">"නිදහස් ආකෘති කවුළු සබල කරන්න (ලෙගසිය)"</string> - <string name="enable_freeform_support_summary" msgid="2242481082356957934">"පරීක්ෂණාත්මක ලෙගසි නිදහස් ආකෘති කවුළු සඳහා සහාය සබල කරන්න."</string> + <string name="enable_freeform_support" msgid="7599125687603914253">"අනියම් හැඩැති කවුළු සබල කරන්න"</string> <string name="local_backup_password_title" msgid="4631017948933578709">"ඩෙස්ක්ටොප් උපස්ථ මුරපදය"</string> <string name="local_backup_password_summary_none" msgid="7646898032616361714">"ඩෙස්ක්ටොප් සම්පූර්ණ උපස්ථ දැනට ආරක්ෂා කර නොමැත"</string> <string name="local_backup_password_summary_change" msgid="1707357670383995567">"ඩෙස්ක්ටොප් සම්පූර්ණ උපස්ථ සඳහා මුරපදය වෙනස් කිරීමට හෝ ඉවත් කිරීමට තට්ටු කරන්න"</string> @@ -496,7 +495,8 @@ <string name="power_charging" msgid="6727132649743436802">"<xliff:g id="LEVEL">%1$s</xliff:g> - <xliff:g id="STATE">%2$s</xliff:g>"</string> <string name="power_remaining_charging_duration_only" msgid="8085099012811384899">"සම්පූර්ණ වීමට <xliff:g id="TIME">%1$s</xliff:g>ක් ඉතිරියි"</string> <string name="power_charging_duration" msgid="6127154952524919719">"<xliff:g id="LEVEL">%1$s</xliff:g> - සම්පූර්ණ වීමට <xliff:g id="TIME">%2$s</xliff:g>ක් ඉතිරියි"</string> - <string name="power_charging_limited" msgid="8202147604844938236">"<xliff:g id="LEVEL">%1$s</xliff:g> - ආරෝපණය ප්රශස්ත කර ඇත"</string> + <!-- no translation found for power_charging_limited (4144004473976005214) --> + <skip /> <string name="power_charging_future_paused" msgid="1809543660923642799">"<xliff:g id="LEVEL">%1$s</xliff:g> - ආරෝපණය වේ"</string> <string name="power_fast_charging_duration_v2" msgid="3797735998640359490">"<xliff:g id="LEVEL">%1$s</xliff:g> - <xliff:g id="STATUS">%2$s</xliff:g> - <xliff:g id="TIME">%3$s</xliff:g> හට පෙර සම්පූර්ණයි"</string> <string name="power_charging_duration_v2" msgid="2938998284074003248">"<xliff:g id="LEVEL">%1$s</xliff:g> - <xliff:g id="TIME">%2$s</xliff:g> හට පෙර සම්පූර්ණයෙන් ආරෝපණ වෙයි"</string> diff --git a/packages/SettingsLib/res/values-sk/strings.xml b/packages/SettingsLib/res/values-sk/strings.xml index 6bf0cdba4d7a..189e729130ec 100644 --- a/packages/SettingsLib/res/values-sk/strings.xml +++ b/packages/SettingsLib/res/values-sk/strings.xml @@ -430,8 +430,7 @@ <string name="force_allow_on_external_summary" msgid="8525425782530728238">"Umožniť zapísať akúkoľvek aplikáciu do externého úložiska bez ohľadu na hodnoty v manifeste"</string> <string name="force_resizable_activities" msgid="7143612144399959606">"Vynútiť možnosť zmeny veľkosti aktivít"</string> <string name="force_resizable_activities_summary" msgid="2490382056981583062">"Umožniť zmeniť veľkosť všetkých aktivít na niekoľko okien (bez ohľadu na hodnoty manifestu)"</string> - <string name="enable_freeform_support" msgid="8409932201445109106">"Povolenie meniteľných okien (starých)"</string> - <string name="enable_freeform_support_summary" msgid="2242481082356957934">"Povoľte podporu pre experimentálne staré meniteľné okná."</string> + <string name="enable_freeform_support" msgid="7599125687603914253">"Povoliť okná s voľným tvarom"</string> <string name="local_backup_password_title" msgid="4631017948933578709">"Heslo pre zálohy v počítači"</string> <string name="local_backup_password_summary_none" msgid="7646898032616361714">"Úplné zálohy v počítači nie sú momentálne chránené"</string> <string name="local_backup_password_summary_change" msgid="1707357670383995567">"Klepnutím zmeníte alebo odstránite heslo pre úplné zálohy do počítača"</string> @@ -496,7 +495,8 @@ <string name="power_charging" msgid="6727132649743436802">"<xliff:g id="LEVEL">%1$s</xliff:g> – <xliff:g id="STATE">%2$s</xliff:g>"</string> <string name="power_remaining_charging_duration_only" msgid="8085099012811384899">"<xliff:g id="TIME">%1$s</xliff:g> do úplného nabitia"</string> <string name="power_charging_duration" msgid="6127154952524919719">"<xliff:g id="LEVEL">%1$s</xliff:g> – <xliff:g id="TIME">%2$s</xliff:g> do úplného nabitia"</string> - <string name="power_charging_limited" msgid="8202147604844938236">"<xliff:g id="LEVEL">%1$s</xliff:g> - Nabíjanie je optimalizované"</string> + <!-- no translation found for power_charging_limited (4144004473976005214) --> + <skip /> <string name="power_charging_future_paused" msgid="1809543660923642799">"<xliff:g id="LEVEL">%1$s</xliff:g> – nabíja sa"</string> <string name="power_fast_charging_duration_v2" msgid="3797735998640359490">"<xliff:g id="LEVEL">%1$s</xliff:g> – <xliff:g id="STATUS">%2$s</xliff:g> – čas do nabitia: <xliff:g id="TIME">%3$s</xliff:g>"</string> <string name="power_charging_duration_v2" msgid="2938998284074003248">"<xliff:g id="LEVEL">%1$s</xliff:g> – čas do úplného nabitia: <xliff:g id="TIME">%2$s</xliff:g>"</string> diff --git a/packages/SettingsLib/res/values-sl/strings.xml b/packages/SettingsLib/res/values-sl/strings.xml index 869958f5ccc4..a7367adcb319 100644 --- a/packages/SettingsLib/res/values-sl/strings.xml +++ b/packages/SettingsLib/res/values-sl/strings.xml @@ -430,8 +430,7 @@ <string name="force_allow_on_external_summary" msgid="8525425782530728238">"Poskrbi, da je ne glede na vrednosti v manifestu mogoče vsako aplikacijo zapisati v zunanjo shrambo."</string> <string name="force_resizable_activities" msgid="7143612144399959606">"Vsili spremembo velikosti za aktivnosti"</string> <string name="force_resizable_activities_summary" msgid="2490382056981583062">"Poskrbi, da je ne glede na vrednosti v manifestu mogoče vsem aktivnostim spremeniti velikost za način z več okni."</string> - <string name="enable_freeform_support" msgid="8409932201445109106">"Omogoči okna svobodne oblike (starejše)"</string> - <string name="enable_freeform_support_summary" msgid="2242481082356957934">"Omogoči podporo za poskusna okna svobodne oblike starejše različice."</string> + <string name="enable_freeform_support" msgid="7599125687603914253">"Omogoči okna svobodne oblike"</string> <string name="local_backup_password_title" msgid="4631017948933578709">"Geslo za varnostno kopijo namizja"</string> <string name="local_backup_password_summary_none" msgid="7646898032616361714">"Popolne varnostne kopije namizja trenutno niso zaščitene."</string> <string name="local_backup_password_summary_change" msgid="1707357670383995567">"Dotaknite se, če želite spremeniti ali odstraniti geslo za popolno varnostno kopiranje namizja"</string> @@ -496,7 +495,8 @@ <string name="power_charging" msgid="6727132649743436802">"<xliff:g id="LEVEL">%1$s</xliff:g> – <xliff:g id="STATE">%2$s</xliff:g>"</string> <string name="power_remaining_charging_duration_only" msgid="8085099012811384899">"Še <xliff:g id="TIME">%1$s</xliff:g> do napolnjenosti"</string> <string name="power_charging_duration" msgid="6127154952524919719">"<xliff:g id="LEVEL">%1$s</xliff:g> – še <xliff:g id="TIME">%2$s</xliff:g> do napolnjenosti"</string> - <string name="power_charging_limited" msgid="8202147604844938236">"<xliff:g id="LEVEL">%1$s</xliff:g> – polnjenje je optimizirano"</string> + <!-- no translation found for power_charging_limited (4144004473976005214) --> + <skip /> <string name="power_charging_future_paused" msgid="1809543660923642799">"<xliff:g id="LEVEL">%1$s</xliff:g> – polnjenje"</string> <string name="power_fast_charging_duration_v2" msgid="3797735998640359490">"<xliff:g id="LEVEL">%1$s</xliff:g> – <xliff:g id="STATUS">%2$s</xliff:g> – popolnoma napolnjena do <xliff:g id="TIME">%3$s</xliff:g>"</string> <string name="power_charging_duration_v2" msgid="2938998284074003248">"<xliff:g id="LEVEL">%1$s</xliff:g> – popolnoma napolnjena do <xliff:g id="TIME">%2$s</xliff:g>"</string> diff --git a/packages/SettingsLib/res/values-sq/strings.xml b/packages/SettingsLib/res/values-sq/strings.xml index 0c1bf6cb4021..688a09886ad1 100644 --- a/packages/SettingsLib/res/values-sq/strings.xml +++ b/packages/SettingsLib/res/values-sq/strings.xml @@ -430,8 +430,7 @@ <string name="force_allow_on_external_summary" msgid="8525425782530728238">"Bën që çdo aplikacion të jetë i përshtatshëm për t\'u shkruar në hapësirën ruajtëse të jashtme, pavarësisht nga vlerat e manifestit"</string> <string name="force_resizable_activities" msgid="7143612144399959606">"Detyro madhësinë e ndryshueshme për aktivitetet"</string> <string name="force_resizable_activities_summary" msgid="2490382056981583062">"Bëj që të gjitha aktivitetet të kenë madhësi të ndryshueshme për përdorimin me shumë dritare, pavarësisht vlerave të manifestit."</string> - <string name="enable_freeform_support" msgid="8409932201445109106">"Aktivizo dritaret me formë të lirë (të vjetra)"</string> - <string name="enable_freeform_support_summary" msgid="2242481082356957934">"Aktivizo mbështetjen për dritaret eksperimentale me formë të lirë të versionit të vjetër."</string> + <string name="enable_freeform_support" msgid="7599125687603914253">"Aktivizo dritaret me formë të lirë"</string> <string name="local_backup_password_title" msgid="4631017948933578709">"Fjalëkalimi i rezervimit të desktopit"</string> <string name="local_backup_password_summary_none" msgid="7646898032616361714">"Rezervimet e plota të desktopit nuk janë të mbrojtura aktualisht"</string> <string name="local_backup_password_summary_change" msgid="1707357670383995567">"Trokit për të ndryshuar ose hequr fjalëkalimin për rezervime të plota të desktopit"</string> @@ -496,7 +495,8 @@ <string name="power_charging" msgid="6727132649743436802">"<xliff:g id="LEVEL">%1$s</xliff:g> - <xliff:g id="STATE">%2$s</xliff:g>"</string> <string name="power_remaining_charging_duration_only" msgid="8085099012811384899">"<xliff:g id="TIME">%1$s</xliff:g> derisa të mbushet"</string> <string name="power_charging_duration" msgid="6127154952524919719">"<xliff:g id="LEVEL">%1$s</xliff:g> - <xliff:g id="TIME">%2$s</xliff:g> derisa të mbushet"</string> - <string name="power_charging_limited" msgid="8202147604844938236">"<xliff:g id="LEVEL">%1$s</xliff:g> - Karikimi u optimizua"</string> + <!-- no translation found for power_charging_limited (4144004473976005214) --> + <skip /> <string name="power_charging_future_paused" msgid="1809543660923642799">"<xliff:g id="LEVEL">%1$s</xliff:g> - Po karikohet"</string> <string name="power_fast_charging_duration_v2" msgid="3797735998640359490">"<xliff:g id="LEVEL">%1$s</xliff:g> - <xliff:g id="STATUS">%2$s</xliff:g> - Plot deri në <xliff:g id="TIME">%3$s</xliff:g>"</string> <string name="power_charging_duration_v2" msgid="2938998284074003248">"<xliff:g id="LEVEL">%1$s</xliff:g> - Karikohet plotësisht deri në <xliff:g id="TIME">%2$s</xliff:g>"</string> diff --git a/packages/SettingsLib/res/values-sr/strings.xml b/packages/SettingsLib/res/values-sr/strings.xml index 2b004cbac886..17f5c2aeb487 100644 --- a/packages/SettingsLib/res/values-sr/strings.xml +++ b/packages/SettingsLib/res/values-sr/strings.xml @@ -430,8 +430,7 @@ <string name="force_allow_on_external_summary" msgid="8525425782530728238">"Омогућава уписивање свих апликација у спољну меморију, без обзира на вредности манифеста"</string> <string name="force_resizable_activities" msgid="7143612144399959606">"Принудно омогући промену величине активности"</string> <string name="force_resizable_activities_summary" msgid="2490382056981583062">"Омогућава промену величине свих активности за режим са више прозора, без обзира на вредности манифеста."</string> - <string name="enable_freeform_support" msgid="8409932201445109106">"Омогући прозоре произвољног формата (застарело)"</string> - <string name="enable_freeform_support_summary" msgid="2242481082356957934">"Омогућава подршку за застареле експерименталне прозоре произвољног формата."</string> + <string name="enable_freeform_support" msgid="7599125687603914253">"Омогући прозоре произвољног формата"</string> <string name="local_backup_password_title" msgid="4631017948933578709">"Лозинка резервне копије за рачунар"</string> <string name="local_backup_password_summary_none" msgid="7646898032616361714">"Резервне копије читавог система тренутно нису заштићене"</string> <string name="local_backup_password_summary_change" msgid="1707357670383995567">"Додирните да бисте променили или уклонили лозинку за прављење резервних копија читавог система на рачунару"</string> @@ -496,7 +495,8 @@ <string name="power_charging" msgid="6727132649743436802">"<xliff:g id="LEVEL">%1$s</xliff:g> – <xliff:g id="STATE">%2$s</xliff:g>"</string> <string name="power_remaining_charging_duration_only" msgid="8085099012811384899">"<xliff:g id="TIME">%1$s</xliff:g> до краја пуњења"</string> <string name="power_charging_duration" msgid="6127154952524919719">"<xliff:g id="LEVEL">%1$s</xliff:g> – <xliff:g id="TIME">%2$s</xliff:g> до краја пуњења"</string> - <string name="power_charging_limited" msgid="8202147604844938236">"<xliff:g id="LEVEL">%1$s</xliff:g> – пуњење је оптимизовано"</string> + <!-- no translation found for power_charging_limited (4144004473976005214) --> + <skip /> <string name="power_charging_future_paused" msgid="1809543660923642799">"<xliff:g id="LEVEL">%1$s</xliff:g> – Пуњење"</string> <string name="power_fast_charging_duration_v2" msgid="3797735998640359490">"<xliff:g id="LEVEL">%1$s</xliff:g> – <xliff:g id="STATUS">%2$s</xliff:g> – Потпуно напуњено до <xliff:g id="TIME">%3$s</xliff:g>"</string> <string name="power_charging_duration_v2" msgid="2938998284074003248">"<xliff:g id="LEVEL">%1$s</xliff:g> – Потпуно напуњено до <xliff:g id="TIME">%2$s</xliff:g>"</string> diff --git a/packages/SettingsLib/res/values-sv/strings.xml b/packages/SettingsLib/res/values-sv/strings.xml index 06ed90e08cf0..c50d3c3cc974 100644 --- a/packages/SettingsLib/res/values-sv/strings.xml +++ b/packages/SettingsLib/res/values-sv/strings.xml @@ -430,8 +430,7 @@ <string name="force_allow_on_external_summary" msgid="8525425782530728238">"Allar appar kan skrivas till extern lagring, oavsett manifestvärden"</string> <string name="force_resizable_activities" msgid="7143612144399959606">"Framtvinga storleksanpassning för aktiviteter"</string> <string name="force_resizable_activities_summary" msgid="2490382056981583062">"Gör det möjligt att ändra storleken på alla aktiviteter i flerfönsterläge, oavsett manifestvärden."</string> - <string name="enable_freeform_support" msgid="8409932201445109106">"Aktivera frihandsfönster (äldre)"</string> - <string name="enable_freeform_support_summary" msgid="2242481082356957934">"Aktivera stöd för äldre experimentella frihandsfönster."</string> + <string name="enable_freeform_support" msgid="7599125687603914253">"Aktivera frihandsfönster"</string> <string name="local_backup_password_title" msgid="4631017948933578709">"Lösenord för säkerhetskopia av datorn"</string> <string name="local_backup_password_summary_none" msgid="7646898032616361714">"De fullständiga säkerhetskopiorna av datorn är för närvarande inte skyddade"</string> <string name="local_backup_password_summary_change" msgid="1707357670383995567">"Tryck om du vill ändra eller ta bort lösenordet för fullständig säkerhetskopiering av datorn"</string> @@ -496,7 +495,8 @@ <string name="power_charging" msgid="6727132649743436802">"<xliff:g id="LEVEL">%1$s</xliff:g> – <xliff:g id="STATE">%2$s</xliff:g>"</string> <string name="power_remaining_charging_duration_only" msgid="8085099012811384899">"<xliff:g id="TIME">%1$s</xliff:g> kvar tills fulladdat"</string> <string name="power_charging_duration" msgid="6127154952524919719">"<xliff:g id="LEVEL">%1$s</xliff:g> – <xliff:g id="TIME">%2$s</xliff:g> kvar tills fulladdat"</string> - <string name="power_charging_limited" msgid="8202147604844938236">"<xliff:g id="LEVEL">%1$s</xliff:g> - Laddningen har optimerats"</string> + <!-- no translation found for power_charging_limited (4144004473976005214) --> + <skip /> <string name="power_charging_future_paused" msgid="1809543660923642799">"<xliff:g id="LEVEL">%1$s</xliff:g> – laddas"</string> <string name="power_fast_charging_duration_v2" msgid="3797735998640359490">"<xliff:g id="LEVEL">%1$s</xliff:g> – <xliff:g id="STATUS">%2$s</xliff:g> – fulladdad till <xliff:g id="TIME">%3$s</xliff:g>"</string> <string name="power_charging_duration_v2" msgid="2938998284074003248">"<xliff:g id="LEVEL">%1$s</xliff:g> – fulladdad till <xliff:g id="TIME">%2$s</xliff:g>"</string> diff --git a/packages/SettingsLib/res/values-sw/strings.xml b/packages/SettingsLib/res/values-sw/strings.xml index 08aa7840a9fc..0c71dd128740 100644 --- a/packages/SettingsLib/res/values-sw/strings.xml +++ b/packages/SettingsLib/res/values-sw/strings.xml @@ -430,8 +430,7 @@ <string name="force_allow_on_external_summary" msgid="8525425782530728238">"Huruhusu programu yoyote iwekwe kwenye hifadhi ya nje, bila kujali thamani za faili ya maelezo"</string> <string name="force_resizable_activities" msgid="7143612144399959606">"Lazimisha shughuli ziweze kubadilishwa ukubwa"</string> <string name="force_resizable_activities_summary" msgid="2490382056981583062">"Fanya shughuli zote ziweze kubadilishwa ukubwa kwenye madirisha mengi, bila kuzingatia thamani za faili ya maelezo."</string> - <string name="enable_freeform_support" msgid="8409932201445109106">"Washa madirisha yenye muundo huru (yaliyopitwa na wakati)"</string> - <string name="enable_freeform_support_summary" msgid="2242481082356957934">"Ruhusu matumizi ya madirisha ya majaribio yenye muundo huru yaliyopitwa na wakati."</string> + <string name="enable_freeform_support" msgid="7599125687603914253">"Washa madirisha yenye muundo huru"</string> <string name="local_backup_password_title" msgid="4631017948933578709">"Nenosiri la hifadhi rudufu ya eneo kazi"</string> <string name="local_backup_password_summary_none" msgid="7646898032616361714">"Hifadhi rudufu kamili za eneo kazi hazijalindwa kwa sasa"</string> <string name="local_backup_password_summary_change" msgid="1707357670383995567">"Gusa ili ubadilishe au uondoe nenosiri la hifadhi rudufu kamili za eneo kazi"</string> @@ -496,7 +495,8 @@ <string name="power_charging" msgid="6727132649743436802">"<xliff:g id="LEVEL">%1$s</xliff:g> - <xliff:g id="STATE">%2$s</xliff:g>"</string> <string name="power_remaining_charging_duration_only" msgid="8085099012811384899">"Zimesalia <xliff:g id="TIME">%1$s</xliff:g> ijae chaji"</string> <string name="power_charging_duration" msgid="6127154952524919719">"<xliff:g id="LEVEL">%1$s</xliff:g> - <xliff:g id="TIME">%2$s</xliff:g> zimesalia ijae chaji"</string> - <string name="power_charging_limited" msgid="8202147604844938236">"<xliff:g id="LEVEL">%1$s</xliff:g> - Hali ya kuchaji imeboreshwa"</string> + <!-- no translation found for power_charging_limited (4144004473976005214) --> + <skip /> <string name="power_charging_future_paused" msgid="1809543660923642799">"<xliff:g id="LEVEL">%1$s</xliff:g> - Inachaji"</string> <string name="power_fast_charging_duration_v2" msgid="3797735998640359490">"<xliff:g id="LEVEL">%1$s</xliff:g> - <xliff:g id="STATUS">%2$s</xliff:g> - Itajaa kufikia <xliff:g id="TIME">%3$s</xliff:g>"</string> <string name="power_charging_duration_v2" msgid="2938998284074003248">"<xliff:g id="LEVEL">%1$s</xliff:g> - Betri itajaa chaji kufikia <xliff:g id="TIME">%2$s</xliff:g>"</string> diff --git a/packages/SettingsLib/res/values-ta/strings.xml b/packages/SettingsLib/res/values-ta/strings.xml index 5972756108f4..2908b6310419 100644 --- a/packages/SettingsLib/res/values-ta/strings.xml +++ b/packages/SettingsLib/res/values-ta/strings.xml @@ -430,8 +430,7 @@ <string name="force_allow_on_external_summary" msgid="8525425782530728238">"மேனிஃபெஸ்ட் மதிப்புகளைப் பொருட்படுத்தாமல், எல்லா ஆப்ஸையும் வெளிப்புறச் சேமிப்பிடத்தில் எழுத அனுமதிக்கும்"</string> <string name="force_resizable_activities" msgid="7143612144399959606">"செயல்பாடுகளை அளவுமாறக்கூடியதாக அமை"</string> <string name="force_resizable_activities_summary" msgid="2490382056981583062">"மேனிஃபெஸ்ட் மதிப்புகளைப் பொருட்படுத்தாமல், பல சாளரத்திற்கு எல்லா செயல்பாடுகளையும் அளவுமாறக்கூடியதாக அமை."</string> - <string name="enable_freeform_support" msgid="8409932201445109106">"குறிப்பிட்ட வடிவமில்லாத சாளரத்தை இயக்குதல் (லெகஸி)"</string> - <string name="enable_freeform_support_summary" msgid="2242481082356957934">"பரிசோதனைக்குரிய, குறிப்பிட்ட வடிவமில்லாத பழைய சாளரங்களுக்கான ஆதரவை இயக்குதல்."</string> + <string name="enable_freeform_support" msgid="7599125687603914253">"குறிப்பிட்ட வடிவமில்லாத சாளரங்களை இயக்கு"</string> <string name="local_backup_password_title" msgid="4631017948933578709">"டெஸ்க்டாப் காப்புப்பிரதி கடவுச்சொல்"</string> <string name="local_backup_password_summary_none" msgid="7646898032616361714">"டெஸ்க்டாப்பின் முழு காப்புப்பிரதிகள் தற்போது பாதுகாக்கப்படவில்லை"</string> <string name="local_backup_password_summary_change" msgid="1707357670383995567">"டெஸ்க்டாப்பின் முழுக் காப்புப் பிரதிகளுக்கான கடவுச்சொல்லை மாற்ற அல்லது அகற்ற, தட்டவும்"</string> @@ -496,7 +495,8 @@ <string name="power_charging" msgid="6727132649743436802">"<xliff:g id="LEVEL">%1$s</xliff:g> - <xliff:g id="STATE">%2$s</xliff:g>"</string> <string name="power_remaining_charging_duration_only" msgid="8085099012811384899">"முழுவதும் சார்ஜாக <xliff:g id="TIME">%1$s</xliff:g> ஆகும்"</string> <string name="power_charging_duration" msgid="6127154952524919719">"<xliff:g id="LEVEL">%1$s</xliff:g> - முழுவதும் சார்ஜாக <xliff:g id="TIME">%2$s</xliff:g> ஆகும்"</string> - <string name="power_charging_limited" msgid="8202147604844938236">"<xliff:g id="LEVEL">%1$s</xliff:g> - சார்ஜிங் மேம்படுத்தப்பட்டது"</string> + <!-- no translation found for power_charging_limited (4144004473976005214) --> + <skip /> <string name="power_charging_future_paused" msgid="1809543660923642799">"<xliff:g id="LEVEL">%1$s</xliff:g> ‑ சார்ஜாகிறது"</string> <string name="power_fast_charging_duration_v2" msgid="3797735998640359490">"<xliff:g id="LEVEL">%1$s</xliff:g> - <xliff:g id="STATUS">%2$s</xliff:g> - <xliff:g id="TIME">%3$s</xliff:g>க்கு முழுமையாகச் சார்ஜாகிவிடும்"</string> <string name="power_charging_duration_v2" msgid="2938998284074003248">"<xliff:g id="LEVEL">%1$s</xliff:g> - <xliff:g id="TIME">%2$s</xliff:g>க்கு முழுமையாகச் சார்ஜாகிவிடும்"</string> diff --git a/packages/SettingsLib/res/values-te/strings.xml b/packages/SettingsLib/res/values-te/strings.xml index 1df1823ea01b..c188bdb8f98e 100644 --- a/packages/SettingsLib/res/values-te/strings.xml +++ b/packages/SettingsLib/res/values-te/strings.xml @@ -430,8 +430,7 @@ <string name="force_allow_on_external_summary" msgid="8525425782530728238">"ఏ యాప్ను అయినా మానిఫెస్ట్ విలువలతో సంబంధం లేకుండా బాహ్య స్టోరేజ్లో సేవ్ చేయడానికి అనుమతిస్తుంది"</string> <string name="force_resizable_activities" msgid="7143612144399959606">"యాక్టివిటీ విండోల సైజ్ మార్చగలిగేలా నిర్బంధించు"</string> <string name="force_resizable_activities_summary" msgid="2490382056981583062">"మానిఫెస్ట్ విలువలతో సంబంధం లేకుండా అన్ని యాక్టివిటీస్ను పలు రకాల విండోల్లో సరిపోయేటట్లు సైజ్ మార్చగలిగేలా చేస్తుంది."</string> - <string name="enable_freeform_support" msgid="8409932201445109106">"ఫ్రీఫార్మ్ విండోలను ఎనేబుల్ చేయండి (లెగసీ)"</string> - <string name="enable_freeform_support_summary" msgid="2242481082356957934">"ప్రయోగాత్మక లెగసీ ఫ్రీఫార్మ్ విండోలకు సంబంధించిన సపోర్ట్ను ఎనేబుల్ చేయండి."</string> + <string name="enable_freeform_support" msgid="7599125687603914253">"స్వతంత్ర రూప విండోలను ఎనేబుల్ చేయండి"</string> <string name="local_backup_password_title" msgid="4631017948933578709">"డెస్క్టాప్ బ్యాకప్ పాస్వర్డ్"</string> <string name="local_backup_password_summary_none" msgid="7646898032616361714">"డెస్క్టాప్ పూర్తి బ్యాకప్లు ప్రస్తుతం రక్షించబడలేదు"</string> <string name="local_backup_password_summary_change" msgid="1707357670383995567">"డెస్క్టాప్ పూర్తి బ్యాకప్ల కోసం పాస్వర్డ్ను మార్చడానికి లేదా తీసివేయడానికి నొక్కండి"</string> @@ -496,7 +495,8 @@ <string name="power_charging" msgid="6727132649743436802">"<xliff:g id="LEVEL">%1$s</xliff:g> - <xliff:g id="STATE">%2$s</xliff:g>"</string> <string name="power_remaining_charging_duration_only" msgid="8085099012811384899">"<xliff:g id="TIME">%1$s</xliff:g>లో పూర్తిగా ఛార్జ్ అవుతుంది"</string> <string name="power_charging_duration" msgid="6127154952524919719">"<xliff:g id="LEVEL">%1$s</xliff:g> - <xliff:g id="TIME">%2$s</xliff:g>లో పూర్తిగా ఛార్జ్ అవుతుంది"</string> - <string name="power_charging_limited" msgid="8202147604844938236">"<xliff:g id="LEVEL">%1$s</xliff:g> - ఛార్జింగ్ ఆప్టిమైజ్ చేయబడింది"</string> + <!-- no translation found for power_charging_limited (4144004473976005214) --> + <skip /> <string name="power_charging_future_paused" msgid="1809543660923642799">"<xliff:g id="LEVEL">%1$s</xliff:g> - ఛార్జ్ అవుతోంది"</string> <string name="power_fast_charging_duration_v2" msgid="3797735998640359490">"<xliff:g id="LEVEL">%1$s</xliff:g> - <xliff:g id="STATUS">%2$s</xliff:g> - <xliff:g id="TIME">%3$s</xliff:g>కు పూర్తవుతుంది"</string> <string name="power_charging_duration_v2" msgid="2938998284074003248">"<xliff:g id="LEVEL">%1$s</xliff:g> - <xliff:g id="TIME">%2$s</xliff:g>కు పూర్తిగా ఛార్జ్ అవుతుంది"</string> diff --git a/packages/SettingsLib/res/values-th/strings.xml b/packages/SettingsLib/res/values-th/strings.xml index c26f02d8636b..b9510a81b2b1 100644 --- a/packages/SettingsLib/res/values-th/strings.xml +++ b/packages/SettingsLib/res/values-th/strings.xml @@ -430,8 +430,7 @@ <string name="force_allow_on_external_summary" msgid="8525425782530728238">"ทำให้เขียนแอปในที่จัดเก็บข้อมูลภายนอกได้ โดยไม่คำนึงถึงค่าในไฟล์ Manifest"</string> <string name="force_resizable_activities" msgid="7143612144399959606">"บังคับให้กิจกรรมปรับขนาดได้"</string> <string name="force_resizable_activities_summary" msgid="2490382056981583062">"ทำให้กิจกรรมทั้งหมดปรับขนาดได้สำหรับหน้าต่างหลายบาน โดยไม่คำนึงถึงค่าในไฟล์ Manifest"</string> - <string name="enable_freeform_support" msgid="8409932201445109106">"เปิดใช้หน้าต่างรูปแบบอิสระ (แบบเดิม)"</string> - <string name="enable_freeform_support_summary" msgid="2242481082356957934">"เปิดใช้การรองรับหน้าต่างรูปแบบอิสระแบบเดิมเวอร์ชันทดลอง"</string> + <string name="enable_freeform_support" msgid="7599125687603914253">"เปิดใช้หน้าต่างรูปแบบอิสระ"</string> <string name="local_backup_password_title" msgid="4631017948933578709">"รหัสผ่านการสำรองข้อมูลในเดสก์ท็อป"</string> <string name="local_backup_password_summary_none" msgid="7646898032616361714">"การสำรองข้อมูลเต็มรูปแบบในเดสก์ท็อปไม่ได้รับการป้องกันในขณะนี้"</string> <string name="local_backup_password_summary_change" msgid="1707357670383995567">"แตะเพื่อเปลี่ยนแปลงหรือลบรหัสผ่านสำหรับการสำรองข้อมูลเต็มรูปแบบในเดสก์ท็อป"</string> @@ -496,7 +495,8 @@ <string name="power_charging" msgid="6727132649743436802">"<xliff:g id="LEVEL">%1$s</xliff:g> - <xliff:g id="STATE">%2$s</xliff:g>"</string> <string name="power_remaining_charging_duration_only" msgid="8085099012811384899">"อีก <xliff:g id="TIME">%1$s</xliff:g>จึงจะเต็ม"</string> <string name="power_charging_duration" msgid="6127154952524919719">"<xliff:g id="LEVEL">%1$s</xliff:g> - อีก <xliff:g id="TIME">%2$s</xliff:g> จึงจะเต็ม"</string> - <string name="power_charging_limited" msgid="8202147604844938236">"<xliff:g id="LEVEL">%1$s</xliff:g> - ปรับการชาร์จให้เหมาะสมแล้ว"</string> + <!-- no translation found for power_charging_limited (4144004473976005214) --> + <skip /> <string name="power_charging_future_paused" msgid="1809543660923642799">"<xliff:g id="LEVEL">%1$s</xliff:g> ‑ กำลังชาร์จ"</string> <string name="power_fast_charging_duration_v2" msgid="3797735998640359490">"<xliff:g id="LEVEL">%1$s</xliff:g> - <xliff:g id="STATUS">%2$s</xliff:g> - จะเต็มภายใน <xliff:g id="TIME">%3$s</xliff:g>"</string> <string name="power_charging_duration_v2" msgid="2938998284074003248">"<xliff:g id="LEVEL">%1$s</xliff:g> - จะชาร์จเต็มภายใน <xliff:g id="TIME">%2$s</xliff:g>"</string> diff --git a/packages/SettingsLib/res/values-tl/strings.xml b/packages/SettingsLib/res/values-tl/strings.xml index 1c038f6a8742..32cc96137a31 100644 --- a/packages/SettingsLib/res/values-tl/strings.xml +++ b/packages/SettingsLib/res/values-tl/strings.xml @@ -430,8 +430,7 @@ <string name="force_allow_on_external_summary" msgid="8525425782530728238">"Ginagawang kwalipikado ang anumang app na mailagay sa external na storage, anuman ang mga value ng manifest"</string> <string name="force_resizable_activities" msgid="7143612144399959606">"Sapilitang gawing resizable ang mga aktibidad"</string> <string name="force_resizable_activities_summary" msgid="2490382056981583062">"Gawing nare-resize ang lahat ng aktibidad para sa multi-window, anuman ang mga value ng manifest."</string> - <string name="enable_freeform_support" msgid="8409932201445109106">"I-enable ang mga freeform window (legacy)"</string> - <string name="enable_freeform_support_summary" msgid="2242481082356957934">"I-enable ang suporta para sa mga pang-eksperimentong legacy na freeform window."</string> + <string name="enable_freeform_support" msgid="7599125687603914253">"I-enable ang mga freeform window"</string> <string name="local_backup_password_title" msgid="4631017948933578709">"Password ng pag-backup ng desktop"</string> <string name="local_backup_password_summary_none" msgid="7646898032616361714">"Kasalukuyang hindi pinoprotektahan ang mga buong pag-backup ng desktop"</string> <string name="local_backup_password_summary_change" msgid="1707357670383995567">"I-tap upang baguhin o alisin ang password para sa mga kumpletong pag-back up sa desktop"</string> @@ -496,7 +495,8 @@ <string name="power_charging" msgid="6727132649743436802">"<xliff:g id="LEVEL">%1$s</xliff:g> - <xliff:g id="STATE">%2$s</xliff:g>"</string> <string name="power_remaining_charging_duration_only" msgid="8085099012811384899">"<xliff:g id="TIME">%1$s</xliff:g> na lang bago mapuno"</string> <string name="power_charging_duration" msgid="6127154952524919719">"<xliff:g id="LEVEL">%1$s</xliff:g> - <xliff:g id="TIME">%2$s</xliff:g> na lang bago mapuno"</string> - <string name="power_charging_limited" msgid="8202147604844938236">"<xliff:g id="LEVEL">%1$s</xliff:g> - Naka-optimize ang pag-charge"</string> + <!-- no translation found for power_charging_limited (4144004473976005214) --> + <skip /> <string name="power_charging_future_paused" msgid="1809543660923642799">"<xliff:g id="LEVEL">%1$s</xliff:g> - Nagcha-charge"</string> <string name="power_fast_charging_duration_v2" msgid="3797735998640359490">"<xliff:g id="LEVEL">%1$s</xliff:g> - <xliff:g id="STATUS">%2$s</xliff:g> - Mapupuno sa <xliff:g id="TIME">%3$s</xliff:g>"</string> <string name="power_charging_duration_v2" msgid="2938998284074003248">"<xliff:g id="LEVEL">%1$s</xliff:g> - Mafu-full charge sa <xliff:g id="TIME">%2$s</xliff:g>"</string> diff --git a/packages/SettingsLib/res/values-tr/strings.xml b/packages/SettingsLib/res/values-tr/strings.xml index 79ace3f79986..6bfc1ee1bb3a 100644 --- a/packages/SettingsLib/res/values-tr/strings.xml +++ b/packages/SettingsLib/res/values-tr/strings.xml @@ -430,8 +430,7 @@ <string name="force_allow_on_external_summary" msgid="8525425782530728238">"Manifest değerlerinden bağımsız olarak uygulamaları harici depolamaya yazmak için uygun hale getirir"</string> <string name="force_resizable_activities" msgid="7143612144399959606">"Etkinlikleri yeniden boyutlandırılabilmeye zorla"</string> <string name="force_resizable_activities_summary" msgid="2490382056981583062">"Manifest değerlerinden bağımsız olarak, tüm etkinlikleri birden fazla pencerede yeniden boyutlandırılabilir yap."</string> - <string name="enable_freeform_support" msgid="8409932201445109106">"Serbest biçimli pencereleri (eski) etkinleştir"</string> - <string name="enable_freeform_support_summary" msgid="2242481082356957934">"Deneysel eski serbest biçimli pencere desteğini etkinleştir."</string> + <string name="enable_freeform_support" msgid="7599125687603914253">"Serbest biçimli pencereleri etkinleştir"</string> <string name="local_backup_password_title" msgid="4631017948933578709">"Masaüstü yedekleme şifresi"</string> <string name="local_backup_password_summary_none" msgid="7646898032616361714">"Masaüstü tam yedeklemeleri şu an korunmuyor"</string> <string name="local_backup_password_summary_change" msgid="1707357670383995567">"Masaüstü tam yedeklemelerinin şifresini değiştirmek veya kaldırmak için dokunun"</string> @@ -496,7 +495,8 @@ <string name="power_charging" msgid="6727132649743436802">"<xliff:g id="LEVEL">%1$s</xliff:g> - <xliff:g id="STATE">%2$s</xliff:g>"</string> <string name="power_remaining_charging_duration_only" msgid="8085099012811384899">"Tamamen şarj olmasına <xliff:g id="TIME">%1$s</xliff:g> kaldı"</string> <string name="power_charging_duration" msgid="6127154952524919719">"<xliff:g id="LEVEL">%1$s</xliff:g> - Tamamen şarj olmasına <xliff:g id="TIME">%2$s</xliff:g> kaldı"</string> - <string name="power_charging_limited" msgid="8202147604844938236">"<xliff:g id="LEVEL">%1$s</xliff:g> - Şarj işlemi optimize edildi"</string> + <!-- no translation found for power_charging_limited (4144004473976005214) --> + <skip /> <string name="power_charging_future_paused" msgid="1809543660923642799">"<xliff:g id="LEVEL">%1$s</xliff:g> ‑ Şarj ediliyor"</string> <string name="power_fast_charging_duration_v2" msgid="3797735998640359490">"<xliff:g id="LEVEL">%1$s</xliff:g> - <xliff:g id="STATUS">%2$s</xliff:g> - Tamamen dolacağı zaman: <xliff:g id="TIME">%3$s</xliff:g>"</string> <string name="power_charging_duration_v2" msgid="2938998284074003248">"<xliff:g id="LEVEL">%1$s</xliff:g> - Tamamen şarj olacağı zaman: <xliff:g id="TIME">%2$s</xliff:g>"</string> diff --git a/packages/SettingsLib/res/values-uk/strings.xml b/packages/SettingsLib/res/values-uk/strings.xml index de416d2f7db8..083a1304e6b6 100644 --- a/packages/SettingsLib/res/values-uk/strings.xml +++ b/packages/SettingsLib/res/values-uk/strings.xml @@ -430,8 +430,7 @@ <string name="force_allow_on_external_summary" msgid="8525425782530728238">"Можна записувати додатки в зовнішню пам’ять, незалежно від значень у маніфесті"</string> <string name="force_resizable_activities" msgid="7143612144399959606">"Примусово масштабувати активність"</string> <string name="force_resizable_activities_summary" msgid="2490382056981583062">"Масштабувати активність на кілька вікон, незалежно від значень у файлі маніфесту."</string> - <string name="enable_freeform_support" msgid="8409932201445109106">"Увімкнути старий формат вікон змінного розміру"</string> - <string name="enable_freeform_support_summary" msgid="2242481082356957934">"Увімкнути підтримку експериментального старого формату вікон змінного розміру."</string> + <string name="enable_freeform_support" msgid="7599125687603914253">"Увімкнути вікна довільного формату"</string> <string name="local_backup_password_title" msgid="4631017948933578709">"Пароль рез. копії на ПК"</string> <string name="local_backup_password_summary_none" msgid="7646898032616361714">"Повні резервні копії на комп’ютері наразі не захищені"</string> <string name="local_backup_password_summary_change" msgid="1707357670383995567">"Торкніться, щоб змінити або видалити пароль для повного резервного копіювання на комп’ютер"</string> @@ -496,7 +495,8 @@ <string name="power_charging" msgid="6727132649743436802">"<xliff:g id="LEVEL">%1$s</xliff:g> – <xliff:g id="STATE">%2$s</xliff:g>"</string> <string name="power_remaining_charging_duration_only" msgid="8085099012811384899">"<xliff:g id="TIME">%1$s</xliff:g> до повного заряду"</string> <string name="power_charging_duration" msgid="6127154952524919719">"<xliff:g id="LEVEL">%1$s</xliff:g> – <xliff:g id="TIME">%2$s</xliff:g> до повного заряду"</string> - <string name="power_charging_limited" msgid="8202147604844938236">"<xliff:g id="LEVEL">%1$s</xliff:g> – заряджання оптимізовано"</string> + <!-- no translation found for power_charging_limited (4144004473976005214) --> + <skip /> <string name="power_charging_future_paused" msgid="1809543660923642799">"<xliff:g id="LEVEL">%1$s</xliff:g> – заряджається"</string> <string name="power_fast_charging_duration_v2" msgid="3797735998640359490">"<xliff:g id="LEVEL">%1$s</xliff:g> - <xliff:g id="STATUS">%2$s</xliff:g> - Завершиться до <xliff:g id="TIME">%3$s</xliff:g>"</string> <string name="power_charging_duration_v2" msgid="2938998284074003248">"<xliff:g id="LEVEL">%1$s</xliff:g> - Повністю зарядиться до <xliff:g id="TIME">%2$s</xliff:g>"</string> diff --git a/packages/SettingsLib/res/values-ur/strings.xml b/packages/SettingsLib/res/values-ur/strings.xml index 309283266417..6508d510b5db 100644 --- a/packages/SettingsLib/res/values-ur/strings.xml +++ b/packages/SettingsLib/res/values-ur/strings.xml @@ -430,8 +430,7 @@ <string name="force_allow_on_external_summary" msgid="8525425782530728238">"manifest اقدار سے قطع نظر، کسی بھی ایپ کو بیرونی اسٹوریج پر لکھے جانے کا اہل بناتا ہے"</string> <string name="force_resizable_activities" msgid="7143612144399959606">"سرگرمیوں کو ری سائز ایبل بنائیں"</string> <string name="force_resizable_activities_summary" msgid="2490382056981583062">"مینی فیسٹ اقدار سے قطع نظر، ملٹی ونڈو کیلئے تمام سرگرمیوں کو ری سائز ایبل بنائیں۔"</string> - <string name="enable_freeform_support" msgid="8409932201445109106">"فریفارم ونڈوز کو فعال کریں (legacy)"</string> - <string name="enable_freeform_support_summary" msgid="2242481082356957934">"تجرباتی legacy فری فارم ونڈوز کیلئے سپورٹ فعال کریں۔"</string> + <string name="enable_freeform_support" msgid="7599125687603914253">"freeform ونڈوز فعال کریں"</string> <string name="local_backup_password_title" msgid="4631017948933578709">"ڈیسک ٹاپ کا بیک اپ پاس ورڈ"</string> <string name="local_backup_password_summary_none" msgid="7646898032616361714">"ڈیسک ٹاپ کے مکمل بیک اپس فی الحال محفوظ کیے ہوئے نہیں ہیں"</string> <string name="local_backup_password_summary_change" msgid="1707357670383995567">"ڈیسک ٹاپ کے مکمل بیک اپس کیلئے پاس ورڈ کو تبدیل کرنے یا ہٹانے کیلئے تھپتھپائیں"</string> @@ -496,7 +495,8 @@ <string name="power_charging" msgid="6727132649743436802">"<xliff:g id="LEVEL">%1$s</xliff:g> - <xliff:g id="STATE">%2$s</xliff:g>"</string> <string name="power_remaining_charging_duration_only" msgid="8085099012811384899">"مکمل چارج ہونے میں <xliff:g id="TIME">%1$s</xliff:g> باقی ہے"</string> <string name="power_charging_duration" msgid="6127154952524919719">"مکمل چارج ہونے میں <xliff:g id="LEVEL">%1$s</xliff:g> - <xliff:g id="TIME">%2$s</xliff:g> باقی ہے"</string> - <string name="power_charging_limited" msgid="8202147604844938236">"<xliff:g id="LEVEL">%1$s</xliff:g> - چارجنگ کو بہتر بنایا گیا"</string> + <!-- no translation found for power_charging_limited (4144004473976005214) --> + <skip /> <string name="power_charging_future_paused" msgid="1809543660923642799">"<xliff:g id="LEVEL">%1$s</xliff:g> - چارج ہو رہی ہے"</string> <string name="power_fast_charging_duration_v2" msgid="3797735998640359490">"<xliff:g id="LEVEL">%1$s</xliff:g> - <xliff:g id="STATUS">%2$s</xliff:g> - <xliff:g id="TIME">%3$s</xliff:g> تک مکمل ہو جائے گی"</string> <string name="power_charging_duration_v2" msgid="2938998284074003248">"<xliff:g id="LEVEL">%1$s</xliff:g> - <xliff:g id="TIME">%2$s</xliff:g> تک مکمل چارج ہو جائے گی"</string> diff --git a/packages/SettingsLib/res/values-uz/strings.xml b/packages/SettingsLib/res/values-uz/strings.xml index 7502412b2d92..738c81595eae 100644 --- a/packages/SettingsLib/res/values-uz/strings.xml +++ b/packages/SettingsLib/res/values-uz/strings.xml @@ -430,8 +430,7 @@ <string name="force_allow_on_external_summary" msgid="8525425782530728238">"Manifest qiymatidan qat’i nazar istalgan ilovani tashqi xotiraga saqlash imkonini beradi"</string> <string name="force_resizable_activities" msgid="7143612144399959606">"Harakatlarni moslashuvchan o‘lchamga keltirish"</string> <string name="force_resizable_activities_summary" msgid="2490382056981583062">"Manifest qiymatidan qat’i nazar barcha harakatlarni ko‘p oynali rejimga moslashtirish."</string> - <string name="enable_freeform_support" msgid="8409932201445109106">"Erkin shakldagi oynalarni (eskirgan) yoqish"</string> - <string name="enable_freeform_support_summary" msgid="2242481082356957934">"Eskirgan erkin shakldagi oynalar yaratish uchun moʻljallangan tajribaviy funksiyani yoqish."</string> + <string name="enable_freeform_support" msgid="7599125687603914253">"Erkin shakldagi oynalarni yoqish"</string> <string name="local_backup_password_title" msgid="4631017948933578709">"Zaxira nusxa uchun parol"</string> <string name="local_backup_password_summary_none" msgid="7646898032616361714">"Kompyuterdagi zaxira nusxalar hozirgi vaqtda himoyalanmagan"</string> <string name="local_backup_password_summary_change" msgid="1707357670383995567">"Ish stoli to‘liq zaxira nusxalari parolini o‘zgartirish yoki o‘chirish uchun bu yerni bosing"</string> @@ -496,7 +495,8 @@ <string name="power_charging" msgid="6727132649743436802">"<xliff:g id="LEVEL">%1$s</xliff:g> – <xliff:g id="STATE">%2$s</xliff:g>"</string> <string name="power_remaining_charging_duration_only" msgid="8085099012811384899">"Toʻlishiga <xliff:g id="TIME">%1$s</xliff:g> qoldi"</string> <string name="power_charging_duration" msgid="6127154952524919719">"<xliff:g id="LEVEL">%1$s</xliff:g> – Toʻlishiga <xliff:g id="TIME">%2$s</xliff:g> qoldi"</string> - <string name="power_charging_limited" msgid="8202147604844938236">"<xliff:g id="LEVEL">%1$s</xliff:g> - Quvvatlash optimallashtirildi"</string> + <!-- no translation found for power_charging_limited (4144004473976005214) --> + <skip /> <string name="power_charging_future_paused" msgid="1809543660923642799">"<xliff:g id="LEVEL">%1$s</xliff:g> - Quvvatlanmoqda"</string> <string name="power_fast_charging_duration_v2" msgid="3797735998640359490">"<xliff:g id="LEVEL">%1$s</xliff:g> - <xliff:g id="STATUS">%2$s</xliff:g> - Toʻladi: <xliff:g id="TIME">%3$s</xliff:g>"</string> <string name="power_charging_duration_v2" msgid="2938998284074003248">"<xliff:g id="LEVEL">%1$s</xliff:g> - Toʻliq quvvatlanadi: <xliff:g id="TIME">%2$s</xliff:g>"</string> diff --git a/packages/SettingsLib/res/values-vi/strings.xml b/packages/SettingsLib/res/values-vi/strings.xml index 02f0aa1c7227..38b4e4fd3727 100644 --- a/packages/SettingsLib/res/values-vi/strings.xml +++ b/packages/SettingsLib/res/values-vi/strings.xml @@ -430,8 +430,7 @@ <string name="force_allow_on_external_summary" msgid="8525425782530728238">"Cho phép ghi mọi ứng dụng đủ điều kiện vào bộ nhớ ngoài, bất kể giá trị tệp kê khai là gì"</string> <string name="force_resizable_activities" msgid="7143612144399959606">"Buộc các hoạt động có thể thay đổi kích thước"</string> <string name="force_resizable_activities_summary" msgid="2490382056981583062">"Cho phép thay đổi kích thước của tất cả các hoạt động cho nhiều cửa sổ, bất kể giá trị tệp kê khai là gì."</string> - <string name="enable_freeform_support" msgid="8409932201445109106">"Bật cửa sổ có thể đổi kích thước (cũ)"</string> - <string name="enable_freeform_support_summary" msgid="2242481082356957934">"Bật tính năng hỗ trợ cửa sổ có thể đổi kích thước thử nghiệm (cũ)."</string> + <string name="enable_freeform_support" msgid="7599125687603914253">"Bật cửa sổ dạng tự do"</string> <string name="local_backup_password_title" msgid="4631017948933578709">"Mật khẩu cho bản sao lưu qua máy tính"</string> <string name="local_backup_password_summary_none" msgid="7646898032616361714">"Các bản sao lưu đầy đủ qua máy tính hiện không được bảo vệ"</string> <string name="local_backup_password_summary_change" msgid="1707357670383995567">"Nhấn để thay đổi hoặc xóa mật khẩu dành cho các bản sao lưu đầy đủ vào máy tính"</string> @@ -496,7 +495,8 @@ <string name="power_charging" msgid="6727132649743436802">"<xliff:g id="LEVEL">%1$s</xliff:g> - <xliff:g id="STATE">%2$s</xliff:g>"</string> <string name="power_remaining_charging_duration_only" msgid="8085099012811384899">"<xliff:g id="TIME">%1$s</xliff:g> nữa là pin đầy"</string> <string name="power_charging_duration" msgid="6127154952524919719">"<xliff:g id="LEVEL">%1$s</xliff:g> – <xliff:g id="TIME">%2$s</xliff:g> nữa là pin đầy"</string> - <string name="power_charging_limited" msgid="8202147604844938236">"<xliff:g id="LEVEL">%1$s</xliff:g> – Quá trình sạc được tối ưu hoá"</string> + <!-- no translation found for power_charging_limited (4144004473976005214) --> + <skip /> <string name="power_charging_future_paused" msgid="1809543660923642799">"<xliff:g id="LEVEL">%1$s</xliff:g> – Đang sạc"</string> <string name="power_fast_charging_duration_v2" msgid="3797735998640359490">"<xliff:g id="LEVEL">%1$s</xliff:g> – <xliff:g id="STATUS">%2$s</xliff:g> – Đến <xliff:g id="TIME">%3$s</xliff:g> pin sẽ đầy"</string> <string name="power_charging_duration_v2" msgid="2938998284074003248">"<xliff:g id="LEVEL">%1$s</xliff:g> – Đến <xliff:g id="TIME">%2$s</xliff:g> pin sẽ đầy"</string> diff --git a/packages/SettingsLib/res/values-zh-rCN/strings.xml b/packages/SettingsLib/res/values-zh-rCN/strings.xml index a551121e0922..21cd4580e24d 100644 --- a/packages/SettingsLib/res/values-zh-rCN/strings.xml +++ b/packages/SettingsLib/res/values-zh-rCN/strings.xml @@ -430,8 +430,7 @@ <string name="force_allow_on_external_summary" msgid="8525425782530728238">"允许将任何应用写入外部存储设备(无论清单值是什么)"</string> <string name="force_resizable_activities" msgid="7143612144399959606">"强制将 activity 设为可调整大小"</string> <string name="force_resizable_activities_summary" msgid="2490382056981583062">"将所有 activity 设为可配合多窗口环境调整大小(无论清单值是什么)。"</string> - <string name="enable_freeform_support" msgid="8409932201445109106">"启用可自由调整的窗口(旧版)"</string> - <string name="enable_freeform_support_summary" msgid="2242481082356957934">"实现对实验性旧版可自由调整的窗口的支持。"</string> + <string name="enable_freeform_support" msgid="7599125687603914253">"启用可自由调整的窗口"</string> <string name="local_backup_password_title" msgid="4631017948933578709">"桌面备份密码"</string> <string name="local_backup_password_summary_none" msgid="7646898032616361714">"桌面完整备份当前未设置密码保护"</string> <string name="local_backup_password_summary_change" msgid="1707357670383995567">"点按即可更改或移除用于保护桌面完整备份的密码"</string> @@ -496,7 +495,8 @@ <string name="power_charging" msgid="6727132649743436802">"<xliff:g id="LEVEL">%1$s</xliff:g> - <xliff:g id="STATE">%2$s</xliff:g>"</string> <string name="power_remaining_charging_duration_only" msgid="8085099012811384899">"还需<xliff:g id="TIME">%1$s</xliff:g>充满"</string> <string name="power_charging_duration" msgid="6127154952524919719">"<xliff:g id="LEVEL">%1$s</xliff:g> - 还需<xliff:g id="TIME">%2$s</xliff:g>充满"</string> - <string name="power_charging_limited" msgid="8202147604844938236">"<xliff:g id="LEVEL">%1$s</xliff:g> - 充电方式已优化"</string> + <!-- no translation found for power_charging_limited (4144004473976005214) --> + <skip /> <string name="power_charging_future_paused" msgid="1809543660923642799">"<xliff:g id="LEVEL">%1$s</xliff:g> - 正在充电"</string> <string name="power_fast_charging_duration_v2" msgid="3797735998640359490">"<xliff:g id="LEVEL">%1$s</xliff:g> - <xliff:g id="STATUS">%2$s</xliff:g> - <xliff:g id="TIME">%3$s</xliff:g> 前充满"</string> <string name="power_charging_duration_v2" msgid="2938998284074003248">"<xliff:g id="LEVEL">%1$s</xliff:g> - <xliff:g id="TIME">%2$s</xliff:g> 前充满"</string> diff --git a/packages/SettingsLib/res/values-zh-rHK/strings.xml b/packages/SettingsLib/res/values-zh-rHK/strings.xml index 6f8c537dafeb..8ad35e657dac 100644 --- a/packages/SettingsLib/res/values-zh-rHK/strings.xml +++ b/packages/SettingsLib/res/values-zh-rHK/strings.xml @@ -430,8 +430,7 @@ <string name="force_allow_on_external_summary" msgid="8525425782530728238">"在任何資訊清單值下,允許將所有符合資格的應用程式寫入到外部儲存完間"</string> <string name="force_resizable_activities" msgid="7143612144399959606">"強制將活動設為可調整尺寸"</string> <string name="force_resizable_activities_summary" msgid="2490382056981583062">"在任何資訊清單值下,允許系統配合多重視窗環境調整所有活動的尺寸。"</string> - <string name="enable_freeform_support" msgid="8409932201445109106">"啟用自由形態視窗 (舊的)"</string> - <string name="enable_freeform_support_summary" msgid="2242481082356957934">"啟用舊的實驗版自由形態視窗的支援功能。"</string> + <string name="enable_freeform_support" msgid="7599125687603914253">"啟用自由形態視窗"</string> <string name="local_backup_password_title" msgid="4631017948933578709">"桌面電腦備份密碼"</string> <string name="local_backup_password_summary_none" msgid="7646898032616361714">"桌面電腦的完整備份目前未受保護"</string> <string name="local_backup_password_summary_change" msgid="1707357670383995567">"輕按即可變更或移除桌面電腦完整備份的密碼"</string> @@ -496,7 +495,8 @@ <string name="power_charging" msgid="6727132649743436802">"<xliff:g id="LEVEL">%1$s</xliff:g> - <xliff:g id="STATE">%2$s</xliff:g>"</string> <string name="power_remaining_charging_duration_only" msgid="8085099012811384899">"<xliff:g id="TIME">%1$s</xliff:g>後充滿電"</string> <string name="power_charging_duration" msgid="6127154952524919719">"<xliff:g id="LEVEL">%1$s</xliff:g> - <xliff:g id="TIME">%2$s</xliff:g>後充滿電"</string> - <string name="power_charging_limited" msgid="8202147604844938236">"<xliff:g id="LEVEL">%1$s</xliff:g> - 已優化充電"</string> + <!-- no translation found for power_charging_limited (4144004473976005214) --> + <skip /> <string name="power_charging_future_paused" msgid="1809543660923642799">"<xliff:g id="LEVEL">%1$s</xliff:g> ‑ 充電中"</string> <string name="power_fast_charging_duration_v2" msgid="3797735998640359490">"<xliff:g id="LEVEL">%1$s</xliff:g> - <xliff:g id="STATUS">%2$s</xliff:g> - 在 <xliff:g id="TIME">%3$s</xliff:g>前充滿電"</string> <string name="power_charging_duration_v2" msgid="2938998284074003248">"<xliff:g id="LEVEL">%1$s</xliff:g> • 在 <xliff:g id="TIME">%2$s</xliff:g>前充滿電"</string> diff --git a/packages/SettingsLib/res/values-zh-rTW/strings.xml b/packages/SettingsLib/res/values-zh-rTW/strings.xml index 2806b0262356..8265bba3b555 100644 --- a/packages/SettingsLib/res/values-zh-rTW/strings.xml +++ b/packages/SettingsLib/res/values-zh-rTW/strings.xml @@ -430,8 +430,7 @@ <string name="force_allow_on_external_summary" msgid="8525425782530728238">"允許將任何應用程式寫入外部儲存空間 (無論資訊清單值為何)"</string> <string name="force_resizable_activities" msgid="7143612144399959606">"將活動強制設為可調整大小"</string> <string name="force_resizable_activities_summary" msgid="2490382056981583062">"將所有活動設為可配合多重視窗環境調整大小 (無論資訊清單值為何)。"</string> - <string name="enable_freeform_support" msgid="8409932201445109106">"啟用自由形式視窗 (舊版)"</string> - <string name="enable_freeform_support_summary" msgid="2242481082356957934">"啟用實驗性舊版自由形式視窗支援功能。"</string> + <string name="enable_freeform_support" msgid="7599125687603914253">"啟用自由形式視窗"</string> <string name="local_backup_password_title" msgid="4631017948933578709">"電腦備份密碼"</string> <string name="local_backup_password_summary_none" msgid="7646898032616361714">"尚未設定密碼保護電腦的完整備份"</string> <string name="local_backup_password_summary_change" msgid="1707357670383995567">"輕觸即可變更或移除電腦完整備份的密碼"</string> @@ -496,7 +495,8 @@ <string name="power_charging" msgid="6727132649743436802">"<xliff:g id="LEVEL">%1$s</xliff:g> - <xliff:g id="STATE">%2$s</xliff:g>"</string> <string name="power_remaining_charging_duration_only" msgid="8085099012811384899">"<xliff:g id="TIME">%1$s</xliff:g>後充飽"</string> <string name="power_charging_duration" msgid="6127154952524919719">"<xliff:g id="LEVEL">%1$s</xliff:g> - <xliff:g id="TIME">%2$s</xliff:g>後充飽"</string> - <string name="power_charging_limited" msgid="8202147604844938236">"<xliff:g id="LEVEL">%1$s</xliff:g> - 充電效能已最佳化"</string> + <!-- no translation found for power_charging_limited (4144004473976005214) --> + <skip /> <string name="power_charging_future_paused" msgid="1809543660923642799">"<xliff:g id="LEVEL">%1$s</xliff:g> - 充電中"</string> <string name="power_fast_charging_duration_v2" msgid="3797735998640359490">"<xliff:g id="LEVEL">%1$s</xliff:g> - <xliff:g id="STATUS">%2$s</xliff:g> - <xliff:g id="TIME">%3$s</xliff:g> 前充飽"</string> <string name="power_charging_duration_v2" msgid="2938998284074003248">"<xliff:g id="LEVEL">%1$s</xliff:g> - <xliff:g id="TIME">%2$s</xliff:g> 前充飽"</string> diff --git a/packages/SettingsLib/res/values-zu/strings.xml b/packages/SettingsLib/res/values-zu/strings.xml index 570c4243f944..b2f46b5e39c3 100644 --- a/packages/SettingsLib/res/values-zu/strings.xml +++ b/packages/SettingsLib/res/values-zu/strings.xml @@ -430,8 +430,7 @@ <string name="force_allow_on_external_summary" msgid="8525425782530728238">"Yenza noma uluphi uhlelo lokusebenza lifaneleke ukuthi libhalwe kusitoreji sangaphandle, ngaphandle kwamavelu we-manifest"</string> <string name="force_resizable_activities" msgid="7143612144399959606">"Imisebenzi yamandla izonikezwa usayizi omusha"</string> <string name="force_resizable_activities_summary" msgid="2490382056981583062">"Yenza yonke imisebenzi ibe nosayizi abasha kumawindi amaningi, ngokunganaki amavelu e-manifest."</string> - <string name="enable_freeform_support" msgid="8409932201445109106">"Vumela amawindi efreeform (ifa)"</string> - <string name="enable_freeform_support_summary" msgid="2242481082356957934">"Nika amandla amawindi efreeform efa elisahlolwa."</string> + <string name="enable_freeform_support" msgid="7599125687603914253">"Nika amandla amawindi e-freeform"</string> <string name="local_backup_password_title" msgid="4631017948933578709">"Iphasiwedi yokusekela ngokulondoloza ye-Desktop"</string> <string name="local_backup_password_summary_none" msgid="7646898032616361714">"Ukusekela ngokulondoloza okugcwele kwe-Desktop akuvikelekile okwamanje."</string> <string name="local_backup_password_summary_change" msgid="1707357670383995567">"Thepha ukushintsha noma ukususa iphasiwedi yokwenziwa kwezipele ngokugcwele kwideskithophu"</string> @@ -496,7 +495,8 @@ <string name="power_charging" msgid="6727132649743436802">"<xliff:g id="LEVEL">%1$s</xliff:g> - <xliff:g id="STATE">%2$s</xliff:g>"</string> <string name="power_remaining_charging_duration_only" msgid="8085099012811384899">"<xliff:g id="TIME">%1$s</xliff:g> okusele kuze kugcwale"</string> <string name="power_charging_duration" msgid="6127154952524919719">"<xliff:g id="LEVEL">%1$s</xliff:g> - <xliff:g id="TIME">%2$s</xliff:g> okusele kuze kugcwale"</string> - <string name="power_charging_limited" msgid="8202147604844938236">"<xliff:g id="LEVEL">%1$s</xliff:g> - Ukushaja kuthuthukisiwe"</string> + <!-- no translation found for power_charging_limited (4144004473976005214) --> + <skip /> <string name="power_charging_future_paused" msgid="1809543660923642799">"Iku-<xliff:g id="LEVEL">%1$s</xliff:g> ‑ Iyashaja"</string> <string name="power_fast_charging_duration_v2" msgid="3797735998640359490">"<xliff:g id="LEVEL">%1$s</xliff:g> - <xliff:g id="STATUS">%2$s</xliff:g> - Igcwala ngo-<xliff:g id="TIME">%3$s</xliff:g>"</string> <string name="power_charging_duration_v2" msgid="2938998284074003248">"<xliff:g id="LEVEL">%1$s</xliff:g> • Ishajwe ngokugcwele ngo-<xliff:g id="TIME">%2$s</xliff:g>"</string> diff --git a/packages/SettingsLib/res/values/strings.xml b/packages/SettingsLib/res/values/strings.xml index ce997bf15b91..5c4cdb271a2f 100644 --- a/packages/SettingsLib/res/values/strings.xml +++ b/packages/SettingsLib/res/values/strings.xml @@ -1010,8 +1010,8 @@ <!-- UI debug setting: force allow on external summary [CHAR LIMIT=150] --> <string name="force_resizable_activities_summary">Make all activities resizable for multi-window, regardless of manifest values.</string> - <!-- Title for a toggle that enables support for windows to be in freeform (apps run in resizable windows). [CHAR LIMIT=50] --> - <string name="enable_freeform_support">Enable freeform window support</string> + <!-- Title for a toggle that enables support for windows to be in freeform. Freeform windows enables users to freely arrange and resize overlapping apps. [CHAR LIMIT=50] --> + <string name="enable_freeform_support">Enable freeform windows</string> <!-- Local (desktop) backup password menu title [CHAR LIMIT=25] --> <string name="local_backup_password_title">Desktop backup password</string> @@ -1164,7 +1164,7 @@ <!-- [CHAR_LIMIT=40] Label for battery level chart when charging with duration --> <string name="power_charging_duration"><xliff:g id="level">%1$s</xliff:g> - <xliff:g id="time">%2$s</xliff:g> left until full</string> <!-- [CHAR_LIMIT=80] Label for battery level chart when charge been limited --> - <string name="power_charging_limited"><xliff:g id="level">%1$s</xliff:g> - Charging optimized</string> + <string name="power_charging_limited"><xliff:g id="level">%1$s</xliff:g> - Charging on hold to protect battery</string> <!-- [CHAR_LIMIT=80] Label for battery charging future pause --> <string name="power_charging_future_paused"><xliff:g id="level">%1$s</xliff:g> - Charging</string> diff --git a/packages/SettingsLib/src/com/android/settingslib/bluetooth/BluetoothUtils.java b/packages/SettingsLib/src/com/android/settingslib/bluetooth/BluetoothUtils.java index 05431778301c..2573907f95e5 100644 --- a/packages/SettingsLib/src/com/android/settingslib/bluetooth/BluetoothUtils.java +++ b/packages/SettingsLib/src/com/android/settingslib/bluetooth/BluetoothUtils.java @@ -864,7 +864,7 @@ public class BluetoothUtils { if (localBtManager == null) return null; LocalBluetoothLeBroadcast broadcast = localBtManager.getProfileManager().getLeAudioBroadcastProfile(); - if (!broadcast.isEnabled(null)) return null; + if (broadcast == null || !broadcast.isEnabled(null)) return null; int primaryGroupId = getPrimaryGroupIdForBroadcast(contentResolver); if (primaryGroupId == BluetoothCsipSetCoordinator.GROUP_ID_INVALID) return null; LocalBluetoothLeBroadcastAssistant assistant = @@ -883,4 +883,4 @@ public class BluetoothUtils { } return null; } -}
\ No newline at end of file +} diff --git a/packages/SettingsLib/src/com/android/settingslib/bluetooth/devicesettings/shared/model/DeviceSettingModel.kt b/packages/SettingsLib/src/com/android/settingslib/bluetooth/devicesettings/shared/model/DeviceSettingModel.kt new file mode 100644 index 000000000000..db782803937c --- /dev/null +++ b/packages/SettingsLib/src/com/android/settingslib/bluetooth/devicesettings/shared/model/DeviceSettingModel.kt @@ -0,0 +1,62 @@ +/* + * Copyright (C) 2024 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.android.settingslib.bluetooth.devicesettings.shared.model + +import android.content.Intent +import android.graphics.Bitmap +import com.android.settingslib.bluetooth.CachedBluetoothDevice +import com.android.settingslib.bluetooth.devicesettings.DeviceSettingId + +/** Models a device setting. */ +sealed interface DeviceSettingModel { + val cachedDevice: CachedBluetoothDevice + @DeviceSettingId val id: Int + + /** Models a device setting which should be displayed as an action/switch preference. */ + data class ActionSwitchPreference( + override val cachedDevice: CachedBluetoothDevice, + @DeviceSettingId override val id: Int, + val title: String, + val summary: String? = null, + val icon: Bitmap? = null, + val intent: Intent? = null, + val switchState: DeviceSettingStateModel.ActionSwitchPreferenceState? = null, + val isAllowedChangingState: Boolean = true, + val updateState: ((DeviceSettingStateModel.ActionSwitchPreferenceState) -> Unit)? = null, + ) : DeviceSettingModel + + /** Models a device setting which should be displayed as a multi-toggle preference. */ + data class MultiTogglePreference( + override val cachedDevice: CachedBluetoothDevice, + @DeviceSettingId override val id: Int, + val title: String, + val toggles: List<ToggleModel>, + val isActive: Boolean, + val state: DeviceSettingStateModel.MultiTogglePreferenceState, + val isAllowedChangingState: Boolean, + val updateState: (DeviceSettingStateModel.MultiTogglePreferenceState) -> Unit + ) : DeviceSettingModel + + /** Models an unknown preference. */ + data class Unknown( + override val cachedDevice: CachedBluetoothDevice, + @DeviceSettingId override val id: Int + ) : DeviceSettingModel +} + +/** Models a toggle in [DeviceSettingModel.MultiTogglePreference]. */ +data class ToggleModel(val label: String, val icon: Bitmap) diff --git a/packages/SettingsLib/src/com/android/settingslib/bluetooth/devicesettings/shared/model/DeviceSettingStateModel.kt b/packages/SettingsLib/src/com/android/settingslib/bluetooth/devicesettings/shared/model/DeviceSettingStateModel.kt new file mode 100644 index 000000000000..b404bb9be682 --- /dev/null +++ b/packages/SettingsLib/src/com/android/settingslib/bluetooth/devicesettings/shared/model/DeviceSettingStateModel.kt @@ -0,0 +1,40 @@ +/* + * Copyright (C) 2024 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.android.settingslib.bluetooth.devicesettings.shared.model + +import com.android.settingslib.bluetooth.devicesettings.DeviceSettingPreferenceState + +/** Models a device setting state. */ +sealed interface DeviceSettingStateModel { + fun toParcelable(): DeviceSettingPreferenceState + + /** Models a device setting state for action/switch preference. */ + data class ActionSwitchPreferenceState(val checked: Boolean) : DeviceSettingStateModel { + override fun toParcelable() = + com.android.settingslib.bluetooth.devicesettings.ActionSwitchPreferenceState.Builder() + .setChecked(checked) + .build() + } + + /** Models a device setting state for multi-toggle preference. */ + data class MultiTogglePreferenceState(val selectedIndex: Int) : DeviceSettingStateModel { + override fun toParcelable() = + com.android.settingslib.bluetooth.devicesettings.MultiTogglePreferenceState.Builder() + .setState(selectedIndex) + .build() + } +} diff --git a/packages/SettingsLib/src/com/android/settingslib/notification/data/repository/FakeZenModeRepository.kt b/packages/SettingsLib/src/com/android/settingslib/notification/data/repository/FakeZenModeRepository.kt index 87ab6b3ba877..e5d79a1b4aca 100644 --- a/packages/SettingsLib/src/com/android/settingslib/notification/data/repository/FakeZenModeRepository.kt +++ b/packages/SettingsLib/src/com/android/settingslib/notification/data/repository/FakeZenModeRepository.kt @@ -40,6 +40,8 @@ class FakeZenModeRepository : ZenModeRepository { override val modes: Flow<List<ZenMode>> get() = mutableModesFlow.asStateFlow() + private val activeModesDurations = mutableMapOf<String, Duration?>() + init { updateNotificationPolicy() } @@ -64,8 +66,22 @@ class FakeZenModeRepository : ZenModeRepository { mutableModesFlow.value = mutableModesFlow.value.filter { it.id != id } } + fun getMode(id: String): ZenMode? { + return mutableModesFlow.value.find { it.id == id } + } + override fun activateMode(zenMode: ZenMode, duration: Duration?) { activateMode(zenMode.id) + activeModesDurations[zenMode.id] = duration + } + + fun getModeActiveDuration(id: String): Duration? { + if (!activeModesDurations.containsKey(id)) { + throw IllegalArgumentException( + "mode $id not manually activated, you need to call activateMode" + ) + } + return activeModesDurations[id] } override fun deactivateMode(zenMode: ZenMode) { @@ -78,6 +94,7 @@ class FakeZenModeRepository : ZenModeRepository { fun deactivateMode(id: String) { updateModeActiveState(id = id, isActive = false) + activeModesDurations.remove(id) } // Update the active state while maintaining the mode's position in the list diff --git a/packages/SettingsLib/src/com/android/settingslib/notification/modes/ZenMode.java b/packages/SettingsLib/src/com/android/settingslib/notification/modes/ZenMode.java index 990a2d4708cc..88af7ee3a54f 100644 --- a/packages/SettingsLib/src/com/android/settingslib/notification/modes/ZenMode.java +++ b/packages/SettingsLib/src/com/android/settingslib/notification/modes/ZenMode.java @@ -16,6 +16,8 @@ package com.android.settingslib.notification.modes; +import static android.app.AutomaticZenRule.TYPE_SCHEDULE_CALENDAR; +import static android.app.AutomaticZenRule.TYPE_SCHEDULE_TIME; import static android.app.NotificationManager.INTERRUPTION_FILTER_ALL; import static android.app.NotificationManager.INTERRUPTION_FILTER_PRIORITY; import static android.service.notification.SystemZenRules.getTriggerDescriptionForScheduleEvent; @@ -156,6 +158,11 @@ public class ZenMode implements Parcelable { mIsManualDnd = isManualDnd; } + /** Creates a deep copy of this object. */ + public ZenMode copy() { + return new ZenMode(mId, new AutomaticZenRule.Builder(mRule).build(), mStatus, mIsManualDnd); + } + @NonNull public String getId() { return mId; @@ -298,6 +305,17 @@ public class ZenMode implements Parcelable { return mIsManualDnd; } + /** + * A <em>custom manual</em> mode is a mode created by the user, and not yet assigned an + * automatic trigger condition (neither time schedule nor a calendar). + */ + public boolean isCustomManual() { + return isSystemOwned() + && getType() != TYPE_SCHEDULE_TIME + && getType() != TYPE_SCHEDULE_CALENDAR + && !isManualDnd(); + } + public boolean isEnabled() { return mRule.isEnabled(); } diff --git a/packages/SettingsLib/src/com/android/settingslib/volume/data/repository/AudioSharingRepository.kt b/packages/SettingsLib/src/com/android/settingslib/volume/data/repository/AudioSharingRepository.kt index e78b8a738b1c..99d5891818b6 100644 --- a/packages/SettingsLib/src/com/android/settingslib/volume/data/repository/AudioSharingRepository.kt +++ b/packages/SettingsLib/src/com/android/settingslib/volume/data/repository/AudioSharingRepository.kt @@ -62,6 +62,9 @@ interface AudioSharingRepository { /** Whether the device is in audio sharing. */ val inAudioSharing: Flow<Boolean> + /** The primary headset groupId in audio sharing. */ + val primaryGroupId: StateFlow<Int> + /** The secondary headset groupId in audio sharing. */ val secondaryGroupId: StateFlow<Int> @@ -109,6 +112,16 @@ class AudioSharingRepositoryImpl( awaitClose { contentResolver.unregisterContentObserver(callback) } } + override val primaryGroupId: StateFlow<Int> = + primaryChange + .map { BluetoothUtils.getPrimaryGroupIdForBroadcast(contentResolver) } + .onStart { emit(BluetoothUtils.getPrimaryGroupIdForBroadcast(contentResolver)) } + .flowOn(backgroundCoroutineContext) + .stateIn( + coroutineScope, + SharingStarted.WhileSubscribed(), + BluetoothUtils.getPrimaryGroupIdForBroadcast(contentResolver)) + override val secondaryGroupId: StateFlow<Int> = merge( btManager.profileManager.leAudioBroadcastAssistantProfile @@ -121,7 +134,7 @@ class AudioSharingRepositoryImpl( BluetoothProfile.LE_AUDIO_BROADCAST_ASSISTANT } .map { getSecondaryGroupId() }, - primaryChange.map { getSecondaryGroupId() }) + primaryGroupId.map { getSecondaryGroupId() }) .onStart { emit(getSecondaryGroupId()) } .flowOn(backgroundCoroutineContext) .stateIn(coroutineScope, SharingStarted.WhileSubscribed(), getSecondaryGroupId()) @@ -193,6 +206,8 @@ class AudioSharingRepositoryImpl( class AudioSharingRepositoryEmptyImpl : AudioSharingRepository { override val inAudioSharing: Flow<Boolean> = flowOf(false) + override val primaryGroupId: StateFlow<Int> = + MutableStateFlow(BluetoothCsipSetCoordinator.GROUP_ID_INVALID) override val secondaryGroupId: StateFlow<Int> = MutableStateFlow(BluetoothCsipSetCoordinator.GROUP_ID_INVALID) override val volumeMap: StateFlow<GroupIdToVolumes> = MutableStateFlow(emptyMap()) diff --git a/packages/SettingsLib/tests/integ/src/com/android/settingslib/volume/data/repository/AudioSharingRepositoryTest.kt b/packages/SettingsLib/tests/integ/src/com/android/settingslib/volume/data/repository/AudioSharingRepositoryTest.kt index 94595d3be8df..c54a2e4d479b 100644 --- a/packages/SettingsLib/tests/integ/src/com/android/settingslib/volume/data/repository/AudioSharingRepositoryTest.kt +++ b/packages/SettingsLib/tests/integ/src/com/android/settingslib/volume/data/repository/AudioSharingRepositoryTest.kt @@ -131,6 +131,10 @@ class AudioSharingRepositoryTest { `when`(deviceManager.findDevice(device2)).thenReturn(cachedDevice2) `when`(receiveState.bisSyncState).thenReturn(arrayListOf(TEST_RECEIVE_STATE_CONTENT)) `when`(assistant.getAllSources(any())).thenReturn(listOf(receiveState)) + Settings.Secure.putInt( + contentResolver, + BluetoothUtils.getPrimaryGroupIdUriForBroadcast(), + TEST_GROUP_ID_INVALID) underTest = AudioSharingRepositoryImpl( contentResolver, @@ -156,6 +160,22 @@ class AudioSharingRepositoryTest { } @Test + fun primaryGroupIdChange_emitValues() { + testScope.runTest { + val groupIds = mutableListOf<Int?>() + underTest.primaryGroupId.onEach { groupIds.add(it) }.launchIn(backgroundScope) + runCurrent() + triggerContentObserverChange() + runCurrent() + + Truth.assertThat(groupIds) + .containsExactly( + TEST_GROUP_ID_INVALID, + TEST_GROUP_ID2) + } + } + + @Test fun secondaryGroupIdChange_emitValues() { testScope.runTest { val groupIds = mutableListOf<Int?>() @@ -217,7 +237,7 @@ class AudioSharingRepositoryTest { fun setSecondaryVolume_setValue() { testScope.runTest { Settings.Secure.putInt( - context.contentResolver, + contentResolver, BluetoothUtils.getPrimaryGroupIdUriForBroadcast(), TEST_GROUP_ID2) `when`(assistant.allConnectedDevices).thenReturn(listOf(device1, device2)) @@ -248,7 +268,7 @@ class AudioSharingRepositoryTest { private fun triggerSourceAdded() { verify(assistant).registerServiceCallBack(any(), assistantCallbackCaptor.capture()) Settings.Secure.putInt( - context.contentResolver, + contentResolver, BluetoothUtils.getPrimaryGroupIdUriForBroadcast(), TEST_GROUP_ID1) `when`(assistant.allConnectedDevices).thenReturn(listOf(device1, device2)) @@ -259,7 +279,7 @@ class AudioSharingRepositoryTest { verify(assistant).registerServiceCallBack(any(), assistantCallbackCaptor.capture()) `when`(assistant.allConnectedDevices).thenReturn(listOf(device1)) Settings.Secure.putInt( - context.contentResolver, + contentResolver, BluetoothUtils.getPrimaryGroupIdUriForBroadcast(), TEST_GROUP_ID1) assistantCallbackCaptor.value.sourceRemoved(device2) @@ -269,7 +289,7 @@ class AudioSharingRepositoryTest { verify(eventManager).registerCallback(btCallbackCaptor.capture()) `when`(assistant.allConnectedDevices).thenReturn(listOf(device1)) Settings.Secure.putInt( - context.contentResolver, + contentResolver, BluetoothUtils.getPrimaryGroupIdUriForBroadcast(), TEST_GROUP_ID1) btCallbackCaptor.value.onProfileConnectionStateChanged(cachedDevice2, state, profile) @@ -283,7 +303,7 @@ class AudioSharingRepositoryTest { contentObserverCaptor.capture()) `when`(assistant.allConnectedDevices).thenReturn(listOf(device1, device2)) Settings.Secure.putInt( - context.contentResolver, + contentResolver, BluetoothUtils.getPrimaryGroupIdUriForBroadcast(), TEST_GROUP_ID2) contentObserverCaptor.value.primaryChanged() diff --git a/packages/SettingsLib/tests/robotests/src/com/android/settingslib/notification/modes/ZenModeTest.java b/packages/SettingsLib/tests/robotests/src/com/android/settingslib/notification/modes/ZenModeTest.java index e705f97202a3..651e57c184d7 100644 --- a/packages/SettingsLib/tests/robotests/src/com/android/settingslib/notification/modes/ZenModeTest.java +++ b/packages/SettingsLib/tests/robotests/src/com/android/settingslib/notification/modes/ZenModeTest.java @@ -27,6 +27,7 @@ import android.app.AutomaticZenRule; import android.net.Uri; import android.os.Parcel; import android.service.notification.Condition; +import android.service.notification.SystemZenRules; import android.service.notification.ZenModeConfig; import android.service.notification.ZenPolicy; @@ -109,6 +110,61 @@ public class ZenModeTest { } @Test + public void isCustomManual_customManualMode() { + AutomaticZenRule rule = new AutomaticZenRule.Builder("Mode", Uri.parse("x")) + .setPackage(SystemZenRules.PACKAGE_ANDROID) + .setType(AutomaticZenRule.TYPE_OTHER) + .build(); + ZenMode mode = new ZenMode("id", rule, zenConfigRuleFor(rule, false)); + + assertThat(mode.isCustomManual()).isTrue(); + } + + @Test + public void isCustomManual_scheduleTime_false() { + AutomaticZenRule rule = new AutomaticZenRule.Builder("Mode", Uri.parse("x")) + .setPackage(SystemZenRules.PACKAGE_ANDROID) + .setType(AutomaticZenRule.TYPE_SCHEDULE_TIME) + .build(); + ZenMode mode = new ZenMode("id", rule, zenConfigRuleFor(rule, false)); + + assertThat(mode.isCustomManual()).isFalse(); + } + + @Test + public void isCustomManual_scheduleCalendar_false() { + AutomaticZenRule rule = new AutomaticZenRule.Builder("Mode", Uri.parse("x")) + .setPackage(SystemZenRules.PACKAGE_ANDROID) + .setType(AutomaticZenRule.TYPE_SCHEDULE_CALENDAR) + .build(); + ZenMode mode = new ZenMode("id", rule, zenConfigRuleFor(rule, false)); + + assertThat(mode.isCustomManual()).isFalse(); + } + + @Test + public void isCustomManual_appProvidedMode_false() { + AutomaticZenRule rule = new AutomaticZenRule.Builder("Mode", Uri.parse("x")) + .setPackage("com.some.package") + .setType(AutomaticZenRule.TYPE_OTHER) + .build(); + ZenMode mode = new ZenMode("id", rule, zenConfigRuleFor(rule, false)); + + assertThat(mode.isCustomManual()).isFalse(); + } + + @Test + public void isCustomManual_manualDnd_false() { + AutomaticZenRule dndRule = new AutomaticZenRule.Builder("Mode", Uri.parse("x")) + .setPackage(SystemZenRules.PACKAGE_ANDROID) + .setType(AutomaticZenRule.TYPE_OTHER) + .build(); + ZenMode mode = ZenMode.manualDndMode(dndRule, false); + + assertThat(mode.isCustomManual()).isFalse(); + } + + @Test public void getPolicy_interruptionFilterPriority_returnsZenPolicy() { AutomaticZenRule azr = new AutomaticZenRule.Builder("Rule", Uri.EMPTY) .setInterruptionFilter(INTERRUPTION_FILTER_PRIORITY) diff --git a/packages/SettingsProvider/src/android/provider/settings/backup/SecureSettings.java b/packages/SettingsProvider/src/android/provider/settings/backup/SecureSettings.java index 2b8b23e3dba8..40a8199a0690 100644 --- a/packages/SettingsProvider/src/android/provider/settings/backup/SecureSettings.java +++ b/packages/SettingsProvider/src/android/provider/settings/backup/SecureSettings.java @@ -253,6 +253,7 @@ public class SecureSettings { Settings.Secure.CUSTOM_BUGREPORT_HANDLER_APP, Settings.Secure.CUSTOM_BUGREPORT_HANDLER_USER, Settings.Secure.CONTEXTUAL_SCREEN_TIMEOUT_ENABLED, + Settings.Secure.HINGE_ANGLE_LIDEVENT_ENABLED, Settings.Secure.LOCK_SCREEN_WEATHER_ENABLED, Settings.Secure.HEARING_AID_RINGTONE_ROUTING, Settings.Secure.HEARING_AID_CALL_ROUTING, diff --git a/packages/SettingsProvider/src/android/provider/settings/validators/SecureSettingsValidators.java b/packages/SettingsProvider/src/android/provider/settings/validators/SecureSettingsValidators.java index cc5302bdd99a..3b9c68389632 100644 --- a/packages/SettingsProvider/src/android/provider/settings/validators/SecureSettingsValidators.java +++ b/packages/SettingsProvider/src/android/provider/settings/validators/SecureSettingsValidators.java @@ -406,6 +406,7 @@ public class SecureSettingsValidators { VALIDATORS.put(Secure.CUSTOM_BUGREPORT_HANDLER_USER, ANY_INTEGER_VALIDATOR); VALIDATORS.put(Secure.LOCK_SCREEN_WEATHER_ENABLED, BOOLEAN_VALIDATOR); VALIDATORS.put(Secure.CONTEXTUAL_SCREEN_TIMEOUT_ENABLED, BOOLEAN_VALIDATOR); + VALIDATORS.put(Secure.HINGE_ANGLE_LIDEVENT_ENABLED, BOOLEAN_VALIDATOR); VALIDATORS.put(Secure.HEARING_AID_RINGTONE_ROUTING, new DiscreteValueValidator(new String[] {"0", "1", "2"})); VALIDATORS.put(Secure.HEARING_AID_CALL_ROUTING, diff --git a/packages/SystemUI/AndroidManifest.xml b/packages/SystemUI/AndroidManifest.xml index 666d939257dc..9f3c2bfb237a 100644 --- a/packages/SystemUI/AndroidManifest.xml +++ b/packages/SystemUI/AndroidManifest.xml @@ -482,7 +482,7 @@ android:exported="true" android:theme="@style/Theme.AppCompat.NoActionBar"> <intent-filter> - <action android:name="com.android.systemui.action.TOUCHPAD_TUTORIAL"/> + <action android:name="com.android.systemui.action.TOUCHPAD_KEYBOARD_TUTORIAL"/> <category android:name="android.intent.category.DEFAULT"/> </intent-filter> </activity> @@ -1062,6 +1062,14 @@ </intent-filter> </receiver> + <receiver android:name=".accessibility.extradim.ExtraDimDialogReceiver" + android:singleUser="true" + android:exported="false"> + <intent-filter android:priority="1"> + <action android:name="com.android.systemui.action.LAUNCH_REMOVE_EXTRA_DIM_DIALOG" /> + </intent-filter> + </receiver> + <activity android:name=".logcat.LogAccessDialogActivity" android:theme="@android:style/Theme.Translucent.NoTitleBar" android:excludeFromRecents="true" diff --git a/packages/SystemUI/aconfig/accessibility.aconfig b/packages/SystemUI/aconfig/accessibility.aconfig index 08614540c330..8860452905bd 100644 --- a/packages/SystemUI/aconfig/accessibility.aconfig +++ b/packages/SystemUI/aconfig/accessibility.aconfig @@ -90,6 +90,16 @@ flag { } flag { + name: "update_corner_radius_on_display_changed" + namespace: "accessibility" + description: "Updates the corner radius to the magnification fullscreen border when the display changes." + bug: "335113174" + metadata { + purpose: PURPOSE_BUGFIX + } +} + +flag { name: "hearing_devices_dialog_related_tools" namespace: "accessibility" description: "Shows the related tools for hearing devices dialog." diff --git a/packages/SystemUI/aconfig/systemui.aconfig b/packages/SystemUI/aconfig/systemui.aconfig index e4f27aa35ac5..0d337eb948ad 100644 --- a/packages/SystemUI/aconfig/systemui.aconfig +++ b/packages/SystemUI/aconfig/systemui.aconfig @@ -1005,6 +1005,16 @@ flag { } flag { + name: "communal_timer_flicker_fix" + namespace: "systemui" + description: "fixes timers on the hub flickering when pausing" + bug: "353801573" + metadata { + purpose: PURPOSE_BUGFIX + } +} + +flag { name: "app_clips_backlinks" namespace: "systemui" description: "Enables Backlinks improvement feature in App Clips" @@ -1217,6 +1227,9 @@ flag { namespace: "systemui" description: "Enables fullscreen vertical swiping in hub mode to bring up and down the bouncer and shade" bug: "340177049" + metadata { + purpose: PURPOSE_BUGFIX + } } flag { @@ -1250,6 +1263,16 @@ flag { } flag { + name: "use_transitions_for_keyguard_occluded" + namespace: "systemui" + description: "Use Keyguard Transitions to set Notification Shade occlusion state" + bug: "344716537" + metadata { + purpose: PURPOSE_BUGFIX + } +} + +flag { name: "lockscreen_preview_renderer_create_on_main_thread" namespace: "systemui" description: "Force preview renderer to be created on the main thread" diff --git a/packages/SystemUI/compose/features/src/com/android/systemui/communal/ui/compose/CommunalContainer.kt b/packages/SystemUI/compose/features/src/com/android/systemui/communal/ui/compose/CommunalContainer.kt index 8245cc545230..368085f3018a 100644 --- a/packages/SystemUI/compose/features/src/com/android/systemui/communal/ui/compose/CommunalContainer.kt +++ b/packages/SystemUI/compose/features/src/com/android/systemui/communal/ui/compose/CommunalContainer.kt @@ -7,6 +7,7 @@ import androidx.compose.animation.core.infiniteRepeatable import androidx.compose.animation.core.rememberInfiniteTransition import androidx.compose.animation.core.tween import androidx.compose.foundation.background +import androidx.compose.foundation.focusable import androidx.compose.foundation.gestures.Orientation import androidx.compose.foundation.isSystemInDarkTheme import androidx.compose.foundation.layout.Box @@ -25,9 +26,13 @@ import androidx.compose.ui.graphics.BlendMode import androidx.compose.ui.graphics.Brush import androidx.compose.ui.graphics.Color import androidx.compose.ui.platform.LocalDensity +import androidx.compose.ui.semantics.clearAndSetSemantics +import androidx.compose.ui.semantics.contentDescription +import androidx.compose.ui.semantics.semantics import androidx.compose.ui.unit.dp import androidx.lifecycle.compose.collectAsStateWithLifecycle import com.android.compose.animation.scene.Back +import com.android.compose.animation.scene.ContentKey import com.android.compose.animation.scene.Edge import com.android.compose.animation.scene.ElementKey import com.android.compose.animation.scene.ElementMatcher @@ -41,6 +46,7 @@ import com.android.compose.animation.scene.SwipeDirection import com.android.compose.animation.scene.observableTransitionState import com.android.compose.animation.scene.transitions import com.android.compose.theme.LocalAndroidColorScheme +import com.android.internal.R.attr.focusable import com.android.systemui.Flags.glanceableHubBackGesture import com.android.systemui.communal.shared.model.CommunalBackgroundType import com.android.systemui.communal.shared.model.CommunalScenes @@ -65,7 +71,7 @@ object Communal { } object AllElements : ElementMatcher { - override fun matches(key: ElementKey, scene: SceneKey) = true + override fun matches(key: ElementKey, content: ContentKey) = true } private object TransitionDuration { @@ -207,6 +213,8 @@ fun CommunalContainer( backgroundType = backgroundType, colors = colors, content = content, + viewModel = viewModel, + modifier = Modifier.horizontalNestedScrollToScene(), ) } } @@ -222,17 +230,41 @@ private fun SceneScope.CommunalScene( backgroundType: CommunalBackgroundType, colors: CommunalColors, content: CommunalContent, + viewModel: CommunalViewModel, modifier: Modifier = Modifier, ) { - Box(modifier = Modifier.element(Communal.Elements.Scrim).fillMaxSize()) { + val isFocusable by viewModel.isFocusable.collectAsStateWithLifecycle(initialValue = false) + + Box( + modifier = + Modifier.element(Communal.Elements.Scrim) + .fillMaxSize() + .then( + if (isFocusable) { + Modifier.focusable() + } else { + Modifier.semantics { contentDescription = "" }.clearAndSetSemantics {} + } + ) + ) { when (backgroundType) { CommunalBackgroundType.STATIC -> DefaultBackground(colors = colors) CommunalBackgroundType.STATIC_GRADIENT -> StaticLinearGradient() CommunalBackgroundType.ANIMATED -> AnimatedLinearGradient() CommunalBackgroundType.NONE -> BackgroundTopScrim() } + + with(content) { + Content( + modifier = + modifier.focusable(isFocusable).semantics { + if (!isFocusable) { + contentDescription = "" + } + } + ) + } } - with(content) { Content(modifier = modifier) } } /** Default background of the hub, a single color */ diff --git a/packages/SystemUI/compose/features/src/com/android/systemui/communal/ui/compose/CommunalHub.kt b/packages/SystemUI/compose/features/src/com/android/systemui/communal/ui/compose/CommunalHub.kt index b4e513c5137f..69f117431663 100644 --- a/packages/SystemUI/compose/features/src/com/android/systemui/communal/ui/compose/CommunalHub.kt +++ b/packages/SystemUI/compose/features/src/com/android/systemui/communal/ui/compose/CommunalHub.kt @@ -69,8 +69,10 @@ import androidx.compose.foundation.lazy.grid.GridItemSpan import androidx.compose.foundation.lazy.grid.LazyGridState import androidx.compose.foundation.lazy.grid.LazyHorizontalGrid import androidx.compose.foundation.lazy.grid.rememberLazyGridState +import androidx.compose.foundation.rememberScrollState import androidx.compose.foundation.selection.selectable import androidx.compose.foundation.shape.RoundedCornerShape +import androidx.compose.foundation.verticalScroll import androidx.compose.material.icons.Icons import androidx.compose.material.icons.filled.Add import androidx.compose.material.icons.filled.Check @@ -92,6 +94,7 @@ import androidx.compose.material3.OutlinedButton import androidx.compose.material3.Text import androidx.compose.material3.rememberModalBottomSheetState import androidx.compose.runtime.Composable +import androidx.compose.runtime.CompositionLocalProvider import androidx.compose.runtime.LaunchedEffect import androidx.compose.runtime.State import androidx.compose.runtime.derivedStateOf @@ -145,9 +148,11 @@ import androidx.compose.ui.unit.Dp import androidx.compose.ui.unit.IntSize import androidx.compose.ui.unit.LayoutDirection import androidx.compose.ui.unit.dp +import androidx.compose.ui.unit.sp import androidx.compose.ui.unit.times import androidx.compose.ui.util.fastAll import androidx.compose.ui.viewinterop.AndroidView +import androidx.compose.ui.viewinterop.NoOpUpdate import androidx.lifecycle.compose.collectAsStateWithLifecycle import androidx.window.layout.WindowMetricsCalculator import com.android.compose.animation.Easings.Emphasized @@ -155,6 +160,7 @@ import com.android.compose.modifiers.thenIf import com.android.compose.theme.LocalAndroidColorScheme import com.android.compose.ui.graphics.painter.rememberDrawablePainter import com.android.internal.R.dimen.system_app_widget_background_radius +import com.android.systemui.Flags.communalTimerFlickerFix import com.android.systemui.communal.domain.model.CommunalContentModel import com.android.systemui.communal.shared.model.CommunalContentSize import com.android.systemui.communal.shared.model.CommunalScenes @@ -217,7 +223,7 @@ fun CommunalHub( val layoutDirection = LocalLayoutDirection.current if (viewModel.isEditMode) { - ScrollOnNewWidgetAddedEffect(communalContent, gridState) + ObserveNewWidgetAddedEffect(communalContent, gridState, viewModel) } else { ScrollOnUpdatedLiveContentEffect(communalContent, gridState) } @@ -238,48 +244,59 @@ fun CommunalHub( .semantics { testTagsAsResourceId = true } .testTag(COMMUNAL_HUB_TEST_TAG) .fillMaxSize() - .nestedScroll(nestedScrollConnection) - .pointerInput(layoutDirection, gridState, contentOffset, contentListState) { - awaitPointerEventScope { - while (true) { - var event = awaitFirstDown(requireUnconsumed = false) - // Reset touch on first event. - viewModel.onResetTouchState() - - // Process down event in case it's consumed immediately - if (event.isConsumed) { - viewModel.onHubTouchConsumed() - } - - do { - var event = awaitPointerEvent() - for (change in event.changes) { - if (change.isConsumed) { - // Signal touch consumption on any consumed event. - viewModel.onHubTouchConsumed() - } - } - } while ( - !event.changes.fastAll { - it.changedToUp() || it.changedToUpIgnoreConsumed() - } - ) + // Observe taps for selecting items + .thenIf(viewModel.isEditMode) { + Modifier.pointerInput( + layoutDirection, + gridState, + contentOffset, + contentListState, + ) { + observeTaps { offset -> + // if RTL, flip offset direction from Left side to Right + val adjustedOffset = + Offset( + if (layoutDirection == LayoutDirection.Rtl) + screenWidth - offset.x + else offset.x, + offset.y + ) - contentOffset + val index = firstIndexAtOffset(gridState, adjustedOffset) + val key = + index?.let { keyAtIndexIfEditable(contentListState.list, index) } + viewModel.setSelectedKey(key) } } + } + // Nested scroll for full screen swipe to get to shade and bouncer + .thenIf(!viewModel.isEditMode) { + Modifier.nestedScroll(nestedScrollConnection).pointerInput(viewModel) { + awaitPointerEventScope { + while (true) { + val firstDownEvent = awaitFirstDown(requireUnconsumed = false) + // Reset touch on first event. + viewModel.onResetTouchState() + + // Process down event in case it's consumed immediately + if (firstDownEvent.isConsumed) { + viewModel.onHubTouchConsumed() + } - // If not in edit mode, don't allow selecting items. - if (!viewModel.isEditMode) return@pointerInput - observeTaps { offset -> - // if RTL, flip offset direction from Left side to Right - val adjustedOffset = - Offset( - if (layoutDirection == LayoutDirection.Rtl) screenWidth - offset.x - else offset.x, - offset.y - ) - contentOffset - val index = firstIndexAtOffset(gridState, adjustedOffset) - val key = index?.let { keyAtIndexIfEditable(contentListState.list, index) } - viewModel.setSelectedKey(key) + do { + val event = awaitPointerEvent() + for (change in event.changes) { + if (change.isConsumed) { + // Signal touch consumption on any consumed event. + viewModel.onHubTouchConsumed() + } + } + } while ( + !event.changes.fastAll { + it.changedToUp() || it.changedToUpIgnoreConsumed() + } + ) + } + } } } .thenIf(!viewModel.isEditMode && !isEmptyState) { @@ -287,7 +304,7 @@ fun CommunalHub( gridState, contentOffset, communalContent, - gridCoordinates + gridCoordinates, ) { detectLongPressGesture { offset -> // Deduct both grid offset relative to its container and content @@ -549,19 +566,37 @@ private fun ScrollOnUpdatedLiveContentEffect( } } -/** Observes communal content and scrolls to a newly added widget if any. */ +/** + * Observes communal content and determines whether a new widget has been added, upon which case: + * - Announce for accessibility + * - Scroll if the new widget is not visible + */ @Composable -private fun ScrollOnNewWidgetAddedEffect( +private fun ObserveNewWidgetAddedEffect( communalContent: List<CommunalContentModel>, gridState: LazyGridState, + viewModel: BaseCommunalViewModel, ) { val coroutineScope = rememberCoroutineScope() val widgetKeys = remember { mutableListOf<String>() } + var communalContentPending by remember { mutableStateOf(true) } LaunchedEffect(communalContent) { + // Do nothing until any communal content comes in + if (communalContentPending && communalContent.isEmpty()) { + return@LaunchedEffect + } + val oldWidgetKeys = widgetKeys.toList() + val widgets = communalContent.filterIsInstance<CommunalContentModel.WidgetContent.Widget>() widgetKeys.clear() - widgetKeys.addAll(communalContent.filter { it.isWidgetContent() }.map { it.key }) + widgetKeys.addAll(widgets.map { it.key }) + + // Do nothing on first communal content since we don't have a delta + if (communalContentPending) { + communalContentPending = false + return@LaunchedEffect + } // Do nothing if there is no new widget val indexOfFirstNewWidget = widgetKeys.indexOfFirst { !oldWidgetKeys.contains(it) } @@ -569,6 +604,8 @@ private fun ScrollOnNewWidgetAddedEffect( return@LaunchedEffect } + viewModel.onNewWidgetAdded(widgets[indexOfFirstNewWidget].providerInfo) + // Scroll if the new widget is not visible val lastVisibleItemIndex = gridState.layoutInfo.visibleItemsInfo.lastOrNull()?.index if (lastVisibleItemIndex != null && indexOfFirstNewWidget > lastVisibleItemIndex) { @@ -1000,7 +1037,9 @@ private fun CtaTileInViewModeContent( shape = RoundedCornerShape(68.adjustedDp, 34.adjustedDp, 68.adjustedDp, 34.adjustedDp) ) { Column( - modifier = Modifier.fillMaxSize().padding(vertical = 32.dp, horizontal = 50.dp), + modifier = + Modifier.fillMaxSize() + .padding(vertical = 32.adjustedDp, horizontal = 50.adjustedDp), verticalArrangement = Arrangement.Center, horizontalAlignment = Alignment.CenterHorizontally, ) { @@ -1009,47 +1048,57 @@ private fun CtaTileInViewModeContent( contentDescription = stringResource(R.string.cta_label_to_open_widget_picker), modifier = Modifier.size(Dimensions.IconSize).clearAndSetSemantics {}, ) - Spacer(modifier = Modifier.size(6.dp)) + Spacer(modifier = Modifier.size(6.adjustedDp)) Text( text = stringResource(R.string.cta_label_to_edit_widget), style = MaterialTheme.typography.titleLarge, fontSize = nonScalableTextSize(22.dp), lineHeight = nonScalableTextSize(28.dp), + modifier = Modifier.verticalScroll(rememberScrollState()).weight(1F) ) - Spacer(modifier = Modifier.size(16.dp)) + Spacer(modifier = Modifier.size(16.adjustedDp)) Row( - modifier = Modifier.fillMaxWidth().height(56.dp), - horizontalArrangement = Arrangement.spacedBy(16.dp, Alignment.CenterHorizontally), + modifier = Modifier.fillMaxWidth().height(56.adjustedDp), + horizontalArrangement = + Arrangement.spacedBy(16.adjustedDp, Alignment.CenterHorizontally), ) { - OutlinedButton( - modifier = Modifier.fillMaxHeight(), - colors = - ButtonDefaults.buttonColors( - contentColor = colors.onPrimary, - ), - border = BorderStroke(width = 1.0.dp, color = colors.primaryContainer), - contentPadding = PaddingValues(26.dp, 8.dp), - onClick = viewModel::onDismissCtaTile, - ) { - Text( - text = stringResource(R.string.cta_tile_button_to_dismiss), - fontSize = nonScalableTextSize(14.dp), - ) - } - Button( - modifier = Modifier.fillMaxHeight(), - colors = - ButtonDefaults.buttonColors( - containerColor = colors.primaryContainer, - contentColor = colors.onPrimaryContainer, - ), - contentPadding = PaddingValues(26.dp, 8.dp), - onClick = viewModel::onOpenWidgetEditor + CompositionLocalProvider( + LocalDensity provides + Density( + LocalDensity.current.density, + LocalDensity.current.fontScale.coerceIn(0f, 1.25f) + ) ) { - Text( - text = stringResource(R.string.cta_tile_button_to_open_widget_editor), - fontSize = nonScalableTextSize(14.dp), - ) + OutlinedButton( + modifier = Modifier.fillMaxHeight().weight(1F), + colors = + ButtonDefaults.buttonColors( + contentColor = colors.onPrimary, + ), + border = BorderStroke(width = 1.0.dp, color = colors.primaryContainer), + onClick = viewModel::onDismissCtaTile, + contentPadding = PaddingValues(0.dp, 0.dp, 0.dp, 0.dp), + ) { + Text( + text = stringResource(R.string.cta_tile_button_to_dismiss), + fontSize = 14.sp, + ) + } + Button( + modifier = Modifier.fillMaxHeight().weight(1F), + colors = + ButtonDefaults.buttonColors( + containerColor = colors.primaryContainer, + contentColor = colors.onPrimaryContainer, + ), + onClick = viewModel::onOpenWidgetEditor, + contentPadding = PaddingValues(0.dp, 0.dp, 0.dp, 0.dp), + ) { + Text( + text = stringResource(R.string.cta_tile_button_to_open_widget_editor), + fontSize = 14.sp, + ) + } } } } @@ -1320,9 +1369,15 @@ private fun SmartspaceContent( factory = { context -> SmartspaceAppWidgetHostView(context).apply { interactionHandler?.let { setInteractionHandler(it) } - updateAppWidget(model.remoteViews) + if (!communalTimerFlickerFix()) { + updateAppWidget(model.remoteViews) + } } }, + update = + if (communalTimerFlickerFix()) { + { view: SmartspaceAppWidgetHostView -> view.updateAppWidget(model.remoteViews) } + } else NoOpUpdate, // For reusing composition in lazy lists. onReset = {}, ) diff --git a/packages/SystemUI/compose/features/src/com/android/systemui/keyguard/ui/composable/section/NotificationSection.kt b/packages/SystemUI/compose/features/src/com/android/systemui/keyguard/ui/composable/section/NotificationSection.kt index 859c0366a52f..df068c4eb4ef 100644 --- a/packages/SystemUI/compose/features/src/com/android/systemui/keyguard/ui/composable/section/NotificationSection.kt +++ b/packages/SystemUI/compose/features/src/com/android/systemui/keyguard/ui/composable/section/NotificationSection.kt @@ -92,7 +92,7 @@ constructor( fun SceneScope.Notifications(burnInParams: BurnInParameters?, modifier: Modifier = Modifier) { val areNotificationsVisible by lockscreenContentViewModel - .areNotificationsVisible(sceneKey) + .areNotificationsVisible(contentKey) .collectAsStateWithLifecycle(initialValue = false) if (!areNotificationsVisible) { return diff --git a/packages/SystemUI/compose/features/src/com/android/systemui/notifications/ui/composable/NotificationStackNestedScrollConnection.kt b/packages/SystemUI/compose/features/src/com/android/systemui/notifications/ui/composable/NotificationStackNestedScrollConnection.kt new file mode 100644 index 000000000000..4b3a39b367c9 --- /dev/null +++ b/packages/SystemUI/compose/features/src/com/android/systemui/notifications/ui/composable/NotificationStackNestedScrollConnection.kt @@ -0,0 +1,100 @@ +/* + * Copyright (C) 2024 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.android.systemui.notifications.ui.composable + +import androidx.compose.animation.core.Animatable +import androidx.compose.animation.core.tween +import androidx.compose.foundation.gestures.Orientation +import androidx.compose.foundation.layout.offset +import androidx.compose.runtime.Composable +import androidx.compose.runtime.remember +import androidx.compose.ui.Modifier +import androidx.compose.ui.input.nestedscroll.NestedScrollSource +import androidx.compose.ui.input.nestedscroll.nestedScroll +import androidx.compose.ui.unit.IntOffset +import com.android.compose.nestedscroll.PriorityNestedScrollConnection +import kotlin.math.roundToInt +import kotlinx.coroutines.CoroutineScope +import kotlinx.coroutines.launch + +@Composable +fun Modifier.stackVerticalOverscroll( + coroutineScope: CoroutineScope, + canScrollForward: () -> Boolean +): Modifier { + val overscrollOffset = remember { Animatable(0f) } + val stackNestedScrollConnection = remember { + NotificationStackNestedScrollConnection( + stackOffset = { overscrollOffset.value }, + canScrollForward = canScrollForward, + onScroll = { offsetAvailable -> + coroutineScope.launch { + overscrollOffset.snapTo(overscrollOffset.value + offsetAvailable * 0.3f) + } + }, + onStop = { velocityAvailable -> + coroutineScope.launch { + overscrollOffset.animateTo( + targetValue = 0f, + initialVelocity = velocityAvailable, + animationSpec = tween() + ) + } + } + ) + } + + return this.then( + Modifier.nestedScroll(stackNestedScrollConnection).offset { + IntOffset(x = 0, y = overscrollOffset.value.roundToInt()) + } + ) +} + +fun NotificationStackNestedScrollConnection( + stackOffset: () -> Float, + canScrollForward: () -> Boolean, + onStart: (Float) -> Unit = {}, + onScroll: (Float) -> Unit, + onStop: (Float) -> Unit = {}, +): PriorityNestedScrollConnection { + return PriorityNestedScrollConnection( + orientation = Orientation.Vertical, + canStartPreScroll = { _, _ -> false }, + canStartPostScroll = { offsetAvailable, offsetBeforeStart -> + offsetAvailable < 0f && offsetBeforeStart < 0f && !canScrollForward() + }, + canStartPostFling = { velocityAvailable -> velocityAvailable < 0f && !canScrollForward() }, + canContinueScroll = { source -> + if (source == NestedScrollSource.SideEffect) { + stackOffset() > STACK_OVERSCROLL_FLING_MIN_OFFSET + } else { + true + } + }, + canScrollOnFling = true, + onStart = { offsetAvailable -> onStart(offsetAvailable) }, + onScroll = { offsetAvailable -> + onScroll(offsetAvailable) + offsetAvailable + }, + onStop = { velocityAvailable -> + onStop(velocityAvailable) + velocityAvailable + }, + ) +} diff --git a/packages/SystemUI/compose/features/src/com/android/systemui/notifications/ui/composable/Notifications.kt b/packages/SystemUI/compose/features/src/com/android/systemui/notifications/ui/composable/Notifications.kt index c4970c5b43f9..2eb7b3f89af5 100644 --- a/packages/SystemUI/compose/features/src/com/android/systemui/notifications/ui/composable/Notifications.kt +++ b/packages/SystemUI/compose/features/src/com/android/systemui/notifications/ui/composable/Notifications.kt @@ -290,6 +290,7 @@ fun SceneScope.NotificationScrollingStack( val isCurrentGestureOverscroll = viewModel.isCurrentGestureOverscroll.collectAsStateWithLifecycle(false) val expansionFraction by viewModel.expandFraction.collectAsStateWithLifecycle(0f) + val shadeToQsFraction by viewModel.shadeToQsFraction.collectAsStateWithLifecycle(0f) val topPadding = dimensionResource(id = R.dimen.notification_side_paddings) val navBarHeight = WindowInsets.systemBars.asPaddingValues().calculateBottomPadding() @@ -385,14 +386,26 @@ fun SceneScope.NotificationScrollingStack( modifier .element(Notifications.Elements.NotificationScrim) .offset { - // if scrim is expanded while transitioning to Gone scene, increase the offset - // in step with the transition so that it is 0 when it completes. + // if scrim is expanded while transitioning to Gone or QS scene, increase the + // offset in step with the corresponding transition so that it is 0 when it + // completes. if ( scrimOffset.value < 0 && layoutState.isTransitioning(from = Scenes.Shade, to = Scenes.Gone) || layoutState.isTransitioning(from = Scenes.Shade, to = Scenes.Lockscreen) ) { IntOffset(x = 0, y = (scrimOffset.value * expansionFraction).roundToInt()) + } else if ( + scrimOffset.value < 0 && + layoutState.isTransitioning( + from = Scenes.Shade, + to = Scenes.QuickSettings + ) + ) { + IntOffset( + x = 0, + y = (scrimOffset.value * (1 - shadeToQsFraction)).roundToInt() + ) } else { IntOffset(x = 0, y = scrimOffset.value.roundToInt()) } @@ -461,6 +474,7 @@ fun SceneScope.NotificationScrollingStack( .thenIf(shadeMode == ShadeMode.Single) { Modifier.nestedScroll(scrimNestedScrollConnection) } + .stackVerticalOverscroll(coroutineScope) { scrollState.canScrollForward } .verticalScroll(scrollState) .padding(top = topPadding) .fillMaxWidth() @@ -658,3 +672,4 @@ private val DEBUG_HUN_COLOR = Color(0f, 0f, 1f, 0.2f) private val DEBUG_BOX_COLOR = Color(0f, 1f, 0f, 0.2f) private const val HUN_SNOOZE_POSITIONAL_THRESHOLD_FRACTION = 0.25f private const val HUN_SNOOZE_VELOCITY_THRESHOLD = -70f +internal const val STACK_OVERSCROLL_FLING_MIN_OFFSET = -100f diff --git a/packages/SystemUI/compose/scene/src/com/android/compose/animation/scene/AnimateSharedAsState.kt b/packages/SystemUI/compose/scene/src/com/android/compose/animation/scene/AnimateSharedAsState.kt index 114dcf4fbc7e..afbc8e71c940 100644 --- a/packages/SystemUI/compose/scene/src/com/android/compose/animation/scene/AnimateSharedAsState.kt +++ b/packages/SystemUI/compose/scene/src/com/android/compose/animation/scene/AnimateSharedAsState.kt @@ -67,15 +67,15 @@ interface AnimatedState<T> : State<T> { /** * Animate a scene Int value. * - * @see SceneScope.animateSceneValueAsState + * @see ContentScope.animateContentValueAsState */ @Composable -fun SceneScope.animateSceneIntAsState( +fun ContentScope.animateContentIntAsState( value: Int, key: ValueKey, canOverflow: Boolean = true, ): AnimatedState<Int> { - return animateSceneValueAsState(value, key, SharedIntType, canOverflow) + return animateContentValueAsState(value, key, SharedIntType, canOverflow) } /** @@ -107,17 +107,28 @@ private object SharedIntType : SharedValueType<Int, Int> { /** * Animate a scene Float value. * - * @see SceneScope.animateSceneValueAsState + * @see ContentScope.animateContentValueAsState */ @Composable -fun SceneScope.animateSceneFloatAsState( +fun ContentScope.animateContentFloatAsState( value: Float, key: ValueKey, canOverflow: Boolean = true, ): AnimatedState<Float> { - return animateSceneValueAsState(value, key, SharedFloatType, canOverflow) + return animateContentValueAsState(value, key, SharedFloatType, canOverflow) } +@Deprecated( + "Use animateSceneFloatAsState() instead", + replaceWith = ReplaceWith("animateContentFloatAsState(value, key, canOverflow)") +) +@Composable +fun ContentScope.animateSceneFloatAsState( + value: Float, + key: ValueKey, + canOverflow: Boolean = true, +) = animateContentFloatAsState(value, key, canOverflow) + /** * Animate a shared element Float value. * @@ -147,17 +158,28 @@ private object SharedFloatType : SharedValueType<Float, Float> { /** * Animate a scene Dp value. * - * @see SceneScope.animateSceneValueAsState + * @see ContentScope.animateContentValueAsState */ @Composable -fun SceneScope.animateSceneDpAsState( +fun ContentScope.animateContentDpAsState( value: Dp, key: ValueKey, canOverflow: Boolean = true, ): AnimatedState<Dp> { - return animateSceneValueAsState(value, key, SharedDpType, canOverflow) + return animateContentValueAsState(value, key, SharedDpType, canOverflow) } +@Deprecated( + "Use animateSceneDpAsState() instead", + replaceWith = ReplaceWith("animateContentDpAsState(value, key, canOverflow)") +) +@Composable +fun ContentScope.animateSceneDpAsState( + value: Dp, + key: ValueKey, + canOverflow: Boolean = true, +) = animateContentDpAsState(value, key, canOverflow) + /** * Animate a shared element Dp value. * @@ -188,14 +210,14 @@ private object SharedDpType : SharedValueType<Dp, Dp> { /** * Animate a scene Color value. * - * @see SceneScope.animateSceneValueAsState + * @see ContentScope.animateContentValueAsState */ @Composable -fun SceneScope.animateSceneColorAsState( +fun ContentScope.animateContentColorAsState( value: Color, key: ValueKey, ): AnimatedState<Color> { - return animateSceneValueAsState(value, key, SharedColorType, canOverflow = false) + return animateContentValueAsState(value, key, SharedColorType, canOverflow = false) } /** @@ -261,24 +283,24 @@ private class ColorDelta( @Composable internal fun <T> animateSharedValueAsState( layoutImpl: SceneTransitionLayoutImpl, - scene: SceneKey, + content: ContentKey, element: ElementKey?, key: ValueKey, value: T, type: SharedValueType<T, *>, canOverflow: Boolean, ): AnimatedState<T> { - DisposableEffect(layoutImpl, scene, element, key) { - // Create the associated maps that hold the current value for each (element, scene) pair. + DisposableEffect(layoutImpl, content, element, key) { + // Create the associated maps that hold the current value for each (element, content) pair. val valueMap = layoutImpl.sharedValues.getOrPut(key) { mutableMapOf() } val sharedValue = valueMap.getOrPut(element) { SharedValue(type) } as SharedValue<T, *> val targetValues = sharedValue.targetValues - targetValues[scene] = value + targetValues[content] = value onDispose { // Remove the value associated to the current scene, and eventually remove the maps if // they are empty. - targetValues.remove(scene) + targetValues.remove(content) if (targetValues.isEmpty() && valueMap[element] === sharedValue) { valueMap.remove(element) @@ -297,11 +319,11 @@ internal fun <T> animateSharedValueAsState( error("value is equal to $value, which is the undefined value for this type.") } - sharedValue<T, Any>(layoutImpl, key, element).targetValues[scene] = value + sharedValue<T, Any>(layoutImpl, key, element).targetValues[content] = value } - return remember(layoutImpl, scene, element, canOverflow) { - AnimatedStateImpl<T, Any>(layoutImpl, scene, element, key, canOverflow) + return remember(layoutImpl, content, element, canOverflow) { + AnimatedStateImpl<T, Any>(layoutImpl, content, element, key, canOverflow) } } @@ -322,8 +344,8 @@ private fun valueReadTooEarlyMessage(key: ValueKey) = internal class SharedValue<T, Delta>( val type: SharedValueType<T, Delta>, ) { - /** The target value of this shared value for each scene. */ - val targetValues = SnapshotStateMap<SceneKey, T>() + /** The target value of this shared value for each content. */ + val targetValues = SnapshotStateMap<ContentKey, T>() /** The last value of this shared value. */ var lastValue: T = type.unspecifiedValue @@ -340,7 +362,7 @@ internal class SharedValue<T, Delta>( private class AnimatedStateImpl<T, Delta>( private val layoutImpl: SceneTransitionLayoutImpl, - private val scene: SceneKey, + private val content: ContentKey, private val element: ElementKey?, private val key: ValueKey, private val canOverflow: Boolean, @@ -356,14 +378,14 @@ private class AnimatedStateImpl<T, Delta>( // TODO(b/311600838): Remove this. We should not have to fallback to the current // scene value, but we have to because code of removed nodes can still run if they // are placed with a graphics layer. - ?: sharedValue[scene] + ?: sharedValue[content] ?: error(valueReadTooEarlyMessage(key)) val interruptedValue = computeInterruptedValue(sharedValue, transition, value) sharedValue.lastValue = interruptedValue return interruptedValue } - private operator fun SharedValue<T, *>.get(scene: SceneKey): T? = targetValues[scene] + private operator fun SharedValue<T, *>.get(content: ContentKey): T? = targetValues[content] private fun valueOrNull( sharedValue: SharedValue<T, *>, @@ -401,7 +423,7 @@ private class AnimatedStateImpl<T, Delta>( val targetValues = sharedValue.targetValues val transition = if (element != null) { - layoutImpl.elements[element]?.sceneStates?.let { sceneStates -> + layoutImpl.elements[element]?.stateByContent?.let { sceneStates -> layoutImpl.state.currentTransitions.fastLastOrNull { transition -> transition.fromScene in sceneStates || transition.toScene in sceneStates } diff --git a/packages/SystemUI/compose/scene/src/com/android/compose/animation/scene/DraggableHandler.kt b/packages/SystemUI/compose/scene/src/com/android/compose/animation/scene/DraggableHandler.kt index fb13b57176c6..67d1b59d9522 100644 --- a/packages/SystemUI/compose/scene/src/com/android/compose/animation/scene/DraggableHandler.kt +++ b/packages/SystemUI/compose/scene/src/com/android/compose/animation/scene/DraggableHandler.kt @@ -30,6 +30,7 @@ import androidx.compose.ui.unit.IntSize import androidx.compose.ui.unit.dp import androidx.compose.ui.unit.round import com.android.compose.animation.scene.TransitionState.HasOverscrollProperties.Companion.DistanceUnspecified +import com.android.compose.animation.scene.content.Scene import com.android.compose.nestedscroll.PriorityNestedScrollConnection import kotlin.math.absoluteValue import kotlinx.coroutines.CoroutineScope diff --git a/packages/SystemUI/compose/scene/src/com/android/compose/animation/scene/Element.kt b/packages/SystemUI/compose/scene/src/com/android/compose/animation/scene/Element.kt index 3ad07d0b7b4b..0b5e58faf1db 100644 --- a/packages/SystemUI/compose/scene/src/com/android/compose/animation/scene/Element.kt +++ b/packages/SystemUI/compose/scene/src/com/android/compose/animation/scene/Element.kt @@ -48,6 +48,7 @@ import androidx.compose.ui.unit.round import androidx.compose.ui.util.fastCoerceIn import androidx.compose.ui.util.fastLastOrNull import androidx.compose.ui.util.lerp +import com.android.compose.animation.scene.content.Content import com.android.compose.animation.scene.transformation.PropertyTransformation import com.android.compose.animation.scene.transformation.SharedElementTransformation import com.android.compose.ui.util.lerp @@ -57,30 +58,30 @@ import kotlinx.coroutines.launch /** An element on screen, that can be composed in one or more scenes. */ @Stable internal class Element(val key: ElementKey) { - /** The mapping between a scene and the state this element has in that scene, if any. */ + /** The mapping between a content and the state this element has in that content, if any. */ // TODO(b/316901148): Make this a normal map instead once we can make sure that new transitions // are first seen by composition then layout/drawing code. See b/316901148#comment2 for details. - val sceneStates = SnapshotStateMap<SceneKey, SceneState>() + val stateByContent = SnapshotStateMap<ContentKey, State>() /** * The last transition that was used when computing the state (size, position and alpha) of this - * element in any scene, or `null` if it was last laid out when idle. + * element in any content, or `null` if it was last laid out when idle. */ var lastTransition: TransitionState.Transition? = null - /** Whether this element was ever drawn in a scene. */ - var wasDrawnInAnyScene = false + /** Whether this element was ever drawn in a content. */ + var wasDrawnInAnyContent = false override fun toString(): String { return "Element(key=$key)" } - /** The last and target state of this element in a given scene. */ + /** The last and target state of this element in a given content. */ @Stable - class SceneState(val scene: SceneKey) { + class State(val content: ContentKey) { /** - * The *target* state of this element in this scene, i.e. the state of this element when we - * are idle on this scene. + * The *target* state of this element in this content, i.e. the state of this element when + * we are idle on this content. */ var targetSize by mutableStateOf(SizeUnspecified) var targetOffset by mutableStateOf(Offset.Unspecified) @@ -91,7 +92,9 @@ internal class Element(val key: ElementKey) { var lastScale = Scale.Unspecified var lastAlpha = AlphaUnspecified - /** The state of this element in this scene right before the last interruption (if any). */ + /** + * The state of this element in this content right before the last interruption (if any). + */ var offsetBeforeInterruption = Offset.Unspecified var sizeBeforeInterruption = SizeUnspecified var scaleBeforeInterruption = Scale.Unspecified @@ -109,7 +112,7 @@ internal class Element(val key: ElementKey) { var alphaInterruptionDelta = 0f /** - * The attached [ElementNode] a Modifier.element() for a given element and scene. During + * The attached [ElementNode] a Modifier.element() for a given element and content. During * composition, this set could have 0 to 2 elements. After composition and after all * modifier nodes have been attached/detached, this set should contain exactly 1 element. */ @@ -130,19 +133,19 @@ data class Scale(val scaleX: Float, val scaleY: Float, val pivot: Offset = Offse } } -/** The implementation of [SceneScope.element]. */ +/** The implementation of [ContentScope.element]. */ @Stable internal fun Modifier.element( layoutImpl: SceneTransitionLayoutImpl, - scene: Scene, + content: Content, key: ElementKey, ): Modifier { // Make sure that we read the current transitions during composition and not during // layout/drawing. // TODO(b/341072461): Revert this and read the current transitions in ElementNode directly once - // we can ensure that SceneTransitionLayoutImpl will compose new scenes first. + // we can ensure that SceneTransitionLayoutImpl will compose new contents first. val currentTransitions = layoutImpl.state.currentTransitions - return then(ElementModifier(layoutImpl, currentTransitions, scene, key)).testTag(key.testTag) + return then(ElementModifier(layoutImpl, currentTransitions, content, key)).testTag(key.testTag) } /** @@ -152,92 +155,92 @@ internal fun Modifier.element( private data class ElementModifier( private val layoutImpl: SceneTransitionLayoutImpl, private val currentTransitions: List<TransitionState.Transition>, - private val scene: Scene, + private val content: Content, private val key: ElementKey, ) : ModifierNodeElement<ElementNode>() { - override fun create(): ElementNode = ElementNode(layoutImpl, currentTransitions, scene, key) + override fun create(): ElementNode = ElementNode(layoutImpl, currentTransitions, content, key) override fun update(node: ElementNode) { - node.update(layoutImpl, currentTransitions, scene, key) + node.update(layoutImpl, currentTransitions, content, key) } } internal class ElementNode( private var layoutImpl: SceneTransitionLayoutImpl, private var currentTransitions: List<TransitionState.Transition>, - private var scene: Scene, + private var content: Content, private var key: ElementKey, ) : Modifier.Node(), DrawModifierNode, ApproachLayoutModifierNode, TraversableNode { private var _element: Element? = null private val element: Element get() = _element!! - private var _sceneState: Element.SceneState? = null - private val sceneState: Element.SceneState - get() = _sceneState!! + private var _stateInContent: Element.State? = null + private val stateInContent: Element.State + get() = _stateInContent!! override val traverseKey: Any = ElementTraverseKey override fun onAttach() { super.onAttach() - updateElementAndSceneValues() - addNodeToSceneState() + updateElementAndContentValues() + addNodeToContentState() } - private fun updateElementAndSceneValues() { + private fun updateElementAndContentValues() { val element = layoutImpl.elements[key] ?: Element(key).also { layoutImpl.elements[key] = it } _element = element - _sceneState = - element.sceneStates[scene.key] - ?: Element.SceneState(scene.key).also { element.sceneStates[scene.key] = it } + _stateInContent = + element.stateByContent[content.key] + ?: Element.State(content.key).also { element.stateByContent[content.key] = it } } - private fun addNodeToSceneState() { - sceneState.nodes.add(this) + private fun addNodeToContentState() { + stateInContent.nodes.add(this) coroutineScope.launch { // At this point all [CodeLocationNode] have been attached or detached, which means that - // [sceneState.codeLocations] should have exactly 1 element, otherwise this means that - // this element was composed multiple times in the same scene. - val nCodeLocations = sceneState.nodes.size - if (nCodeLocations != 1 || !sceneState.nodes.contains(this@ElementNode)) { - error("$key was composed $nCodeLocations times in ${sceneState.scene}") + // [elementState.codeLocations] should have exactly 1 element, otherwise this means that + // this element was composed multiple times in the same content. + val nCodeLocations = stateInContent.nodes.size + if (nCodeLocations != 1 || !stateInContent.nodes.contains(this@ElementNode)) { + error("$key was composed $nCodeLocations times in ${stateInContent.content}") } } } override fun onDetach() { super.onDetach() - removeNodeFromSceneState() - maybePruneMaps(layoutImpl, element, sceneState) + removeNodeFromContentState() + maybePruneMaps(layoutImpl, element, stateInContent) _element = null - _sceneState = null + _stateInContent = null } - private fun removeNodeFromSceneState() { - sceneState.nodes.remove(this) + private fun removeNodeFromContentState() { + stateInContent.nodes.remove(this) } fun update( layoutImpl: SceneTransitionLayoutImpl, currentTransitions: List<TransitionState.Transition>, - scene: Scene, + content: Content, key: ElementKey, ) { - check(layoutImpl == this.layoutImpl && scene == this.scene) + check(layoutImpl == this.layoutImpl && content == this.content) this.currentTransitions = currentTransitions - removeNodeFromSceneState() + removeNodeFromContentState() val prevElement = this.element - val prevSceneState = this.sceneState + val prevElementState = this.stateInContent this.key = key - updateElementAndSceneValues() + updateElementAndContentValues() - addNodeToSceneState() - maybePruneMaps(layoutImpl, prevElement, prevSceneState) + addNodeToContentState() + maybePruneMaps(layoutImpl, prevElement, prevElementState) } override fun isMeasurementApproachInProgress(lookaheadSize: IntSize): Boolean { @@ -262,15 +265,15 @@ internal class ElementNode( check(isLookingAhead) return measurable.measure(constraints).run { - // Update the size this element has in this scene when idle. - sceneState.targetSize = size() + // Update the size this element has in this content when idle. + stateInContent.targetSize = size() layout(width, height) { // Update the offset (relative to the SceneTransitionLayout) this element has in - // this scene when idle. + // this content when idle. coordinates?.let { coords -> with(layoutImpl.lookaheadScope) { - sceneState.targetOffset = + stateInContent.targetOffset = lookaheadScopeCoordinates.localLookaheadPositionOf(coords) } } @@ -287,22 +290,22 @@ internal class ElementNode( val transition = elementTransition(layoutImpl, element, transitions) // If this element is not supposed to be laid out now, either because it is not part of any - // ongoing transition or the other scene of its transition is overscrolling, then lay out + // ongoing transition or the other content of its transition is overscrolling, then lay out // the element normally and don't place it. val overscrollScene = transition?.currentOverscrollSpec?.scene - val isOtherSceneOverscrolling = overscrollScene != null && overscrollScene != scene.key + val isOtherSceneOverscrolling = overscrollScene != null && overscrollScene != content.key val isNotPartOfAnyOngoingTransitions = transitions.isNotEmpty() && transition == null if (isNotPartOfAnyOngoingTransitions || isOtherSceneOverscrolling) { recursivelyClearPlacementValues() - sceneState.lastSize = Element.SizeUnspecified + stateInContent.lastSize = Element.SizeUnspecified val placeable = measurable.measure(constraints) return layout(placeable.width, placeable.height) { /* Do not place */ } } val placeable = - measure(layoutImpl, element, transition, sceneState, measurable, constraints) - sceneState.lastSize = placeable.size() + measure(layoutImpl, element, transition, stateInContent, measurable, constraints) + stateInContent.lastSize = placeable.size() return layout(placeable.width, placeable.height) { place(transition, placeable) } } @@ -312,12 +315,12 @@ internal class ElementNode( ) { with(layoutImpl.lookaheadScope) { // Update the offset (relative to the SceneTransitionLayout) this element has in this - // scene when idle. + // content when idle. val coords = coordinates ?: error("Element ${element.key} does not have any coordinates") - // No need to place the element in this scene if we don't want to draw it anyways. - if (!shouldPlaceElement(layoutImpl, scene.key, element, transition)) { + // No need to place the element in this content if we don't want to draw it anyways. + if (!shouldPlaceElement(layoutImpl, content.key, element, transition)) { recursivelyClearPlacementValues() return } @@ -326,10 +329,10 @@ internal class ElementNode( val targetOffset = computeValue( layoutImpl, - sceneState, + stateInContent, element, transition, - sceneValue = { it.targetOffset }, + contentValue = { it.targetOffset }, transformation = { it.offset }, currentValue = { currentOffset }, isSpecified = { it != Offset.Unspecified }, @@ -343,17 +346,17 @@ internal class ElementNode( value = targetOffset, unspecifiedValue = Offset.Unspecified, zeroValue = Offset.Zero, - getValueBeforeInterruption = { sceneState.offsetBeforeInterruption }, - setValueBeforeInterruption = { sceneState.offsetBeforeInterruption = it }, - getInterruptionDelta = { sceneState.offsetInterruptionDelta }, + getValueBeforeInterruption = { stateInContent.offsetBeforeInterruption }, + setValueBeforeInterruption = { stateInContent.offsetBeforeInterruption = it }, + getInterruptionDelta = { stateInContent.offsetInterruptionDelta }, setInterruptionDelta = { delta -> setPlacementInterruptionDelta( element = element, - sceneState = sceneState, + stateInContent = stateInContent, transition = transition, delta = delta, - setter = { sceneState, delta -> - sceneState.offsetInterruptionDelta = delta + setter = { stateInContent, delta -> + stateInContent.offsetInterruptionDelta = delta }, ) }, @@ -361,14 +364,15 @@ internal class ElementNode( add = { a, b, bProgress -> a + b * bProgress }, ) - sceneState.lastOffset = interruptedOffset + stateInContent.lastOffset = interruptedOffset val offset = (interruptedOffset - currentOffset).round() if ( - isElementOpaque(scene, element, transition) && - interruptedAlpha(layoutImpl, element, transition, sceneState, alpha = 1f) == 1f + isElementOpaque(content, element, transition) && + interruptedAlpha(layoutImpl, element, transition, stateInContent, alpha = 1f) == + 1f ) { - sceneState.lastAlpha = 1f + stateInContent.lastAlpha = 1f // TODO(b/291071158): Call placeWithLayer() if offset != IntOffset.Zero and size is // not animated once b/305195729 is fixed. Test that drawing is not invalidated in @@ -387,11 +391,11 @@ internal class ElementNode( } val transition = elementTransition(layoutImpl, element, currentTransitions) - if (!shouldPlaceElement(layoutImpl, scene.key, element, transition)) { + if (!shouldPlaceElement(layoutImpl, content.key, element, transition)) { return@placeWithLayer } - alpha = elementAlpha(layoutImpl, element, transition, sceneState) + alpha = elementAlpha(layoutImpl, element, transition, stateInContent) compositingStrategy = CompositingStrategy.ModulateAlpha } } @@ -404,24 +408,24 @@ internal class ElementNode( * for the descendants for which approachMeasure() won't be called. */ private fun recursivelyClearPlacementValues() { - fun Element.SceneState.clearLastPlacementValues() { + fun Element.State.clearLastPlacementValues() { lastOffset = Offset.Unspecified lastScale = Scale.Unspecified lastAlpha = Element.AlphaUnspecified } - sceneState.clearLastPlacementValues() + stateInContent.clearLastPlacementValues() traverseDescendants(ElementTraverseKey) { node -> - (node as ElementNode)._sceneState?.clearLastPlacementValues() + (node as ElementNode)._stateInContent?.clearLastPlacementValues() TraversableNode.Companion.TraverseDescendantsAction.ContinueTraversal } } override fun ContentDrawScope.draw() { - element.wasDrawnInAnyScene = true + element.wasDrawnInAnyContent = true val transition = elementTransition(layoutImpl, element, currentTransitions) - val drawScale = getDrawScale(layoutImpl, element, transition, sceneState) + val drawScale = getDrawScale(layoutImpl, element, transition, stateInContent) if (drawScale == Scale.Default) { drawContent() } else { @@ -441,16 +445,21 @@ internal class ElementNode( private fun maybePruneMaps( layoutImpl: SceneTransitionLayoutImpl, element: Element, - sceneState: Element.SceneState, + stateInContent: Element.State, ) { - // If element is not composed from this scene anymore, remove the scene values. This + // If element is not composed in this content anymore, remove the content values. This // works because [onAttach] is called before [onDetach], so if an element is moved from // the UI tree we will first add the new code location then remove the old one. - if (sceneState.nodes.isEmpty() && element.sceneStates[sceneState.scene] == sceneState) { - element.sceneStates.remove(sceneState.scene) + if ( + stateInContent.nodes.isEmpty() && + element.stateByContent[stateInContent.content] == stateInContent + ) { + element.stateByContent.remove(stateInContent.content) - // If the element is not composed in any scene, remove it from the elements map. - if (element.sceneStates.isEmpty() && layoutImpl.elements[element.key] == element) { + // If the element is not composed in any content, remove it from the elements map. + if ( + element.stateByContent.isEmpty() && layoutImpl.elements[element.key] == element + ) { layoutImpl.elements.remove(element.key) } } @@ -460,7 +469,7 @@ internal class ElementNode( /** * The transition that we should consider for [element]. This is the last transition where one of - * its scenes contains the element. + * its contents contains the element. */ private fun elementTransition( layoutImpl: SceneTransitionLayoutImpl, @@ -469,7 +478,8 @@ private fun elementTransition( ): TransitionState.Transition? { val transition = transitions.fastLastOrNull { transition -> - transition.fromScene in element.sceneStates || transition.toScene in element.sceneStates + transition.fromScene in element.stateByContent || + transition.toScene in element.stateByContent } val previousTransition = element.lastTransition @@ -480,7 +490,7 @@ private fun elementTransition( prepareInterruption(layoutImpl, element, transition, previousTransition) } else if (transition == null && previousTransition != null) { // The transition was just finished. - element.sceneStates.values.forEach { + element.stateByContent.values.forEach { it.clearValuesBeforeInterruption() it.clearInterruptionDeltas() } @@ -499,32 +509,32 @@ private fun prepareInterruption( return } - val sceneStates = element.sceneStates - fun updatedSceneState(key: SceneKey): Element.SceneState? { - return sceneStates[key]?.also { it.selfUpdateValuesBeforeInterruption() } + val stateByContent = element.stateByContent + fun updateStateInContent(key: ContentKey): Element.State? { + return stateByContent[key]?.also { it.selfUpdateValuesBeforeInterruption() } } - val previousFromState = updatedSceneState(previousTransition.fromScene) - val previousToState = updatedSceneState(previousTransition.toScene) - val fromState = updatedSceneState(transition.fromScene) - val toState = updatedSceneState(transition.toScene) + val previousFromState = updateStateInContent(previousTransition.fromScene) + val previousToState = updateStateInContent(previousTransition.toScene) + val fromState = updateStateInContent(transition.fromScene) + val toState = updateStateInContent(transition.toScene) reconcileStates(element, previousTransition) reconcileStates(element, transition) - // Remove the interruption values to all scenes but the scene(s) where the element will be + // Remove the interruption values to all contents but the content(s) where the element will be // placed, to make sure that interruption deltas are computed only right after this interruption // is prepared. - fun cleanInterruptionValues(sceneState: Element.SceneState) { - sceneState.sizeInterruptionDelta = IntSize.Zero - sceneState.offsetInterruptionDelta = Offset.Zero - sceneState.alphaInterruptionDelta = 0f - sceneState.scaleInterruptionDelta = Scale.Zero - - if (!shouldPlaceElement(layoutImpl, sceneState.scene, element, transition)) { - sceneState.offsetBeforeInterruption = Offset.Unspecified - sceneState.alphaBeforeInterruption = Element.AlphaUnspecified - sceneState.scaleBeforeInterruption = Scale.Unspecified + fun cleanInterruptionValues(stateInContent: Element.State) { + stateInContent.sizeInterruptionDelta = IntSize.Zero + stateInContent.offsetInterruptionDelta = Offset.Zero + stateInContent.alphaInterruptionDelta = 0f + stateInContent.scaleInterruptionDelta = Scale.Zero + + if (!shouldPlaceElement(layoutImpl, stateInContent.content, element, transition)) { + stateInContent.offsetBeforeInterruption = Offset.Unspecified + stateInContent.alphaBeforeInterruption = Element.AlphaUnspecified + stateInContent.scaleBeforeInterruption = Scale.Unspecified } } @@ -542,8 +552,8 @@ private fun reconcileStates( element: Element, transition: TransitionState.Transition, ) { - val fromSceneState = element.sceneStates[transition.fromScene] ?: return - val toSceneState = element.sceneStates[transition.toScene] ?: return + val fromSceneState = element.stateByContent[transition.fromScene] ?: return + val toSceneState = element.stateByContent[transition.toScene] ?: return if (!isSharedElementEnabled(element.key, transition)) { return } @@ -563,7 +573,7 @@ private fun reconcileStates( } } -private fun Element.SceneState.selfUpdateValuesBeforeInterruption() { +private fun Element.State.selfUpdateValuesBeforeInterruption() { sizeBeforeInterruption = lastSize if (lastAlpha > 0f) { @@ -571,7 +581,7 @@ private fun Element.SceneState.selfUpdateValuesBeforeInterruption() { scaleBeforeInterruption = lastScale alphaBeforeInterruption = lastAlpha } else { - // Consider the element as not placed in this scene if it was fully transparent. + // Consider the element as not placed in this content if it was fully transparent. // TODO(b/290930950): Look into using derived state inside place() instead to not even place // the element at all when alpha == 0f. offsetBeforeInterruption = Offset.Unspecified @@ -580,7 +590,7 @@ private fun Element.SceneState.selfUpdateValuesBeforeInterruption() { } } -private fun Element.SceneState.updateValuesBeforeInterruption(lastState: Element.SceneState) { +private fun Element.State.updateValuesBeforeInterruption(lastState: Element.State) { offsetBeforeInterruption = lastState.offsetBeforeInterruption sizeBeforeInterruption = lastState.sizeBeforeInterruption scaleBeforeInterruption = lastState.scaleBeforeInterruption @@ -589,14 +599,14 @@ private fun Element.SceneState.updateValuesBeforeInterruption(lastState: Element clearInterruptionDeltas() } -private fun Element.SceneState.clearInterruptionDeltas() { +private fun Element.State.clearInterruptionDeltas() { offsetInterruptionDelta = Offset.Zero sizeInterruptionDelta = IntSize.Zero scaleInterruptionDelta = Scale.Zero alphaInterruptionDelta = 0f } -private fun Element.SceneState.clearValuesBeforeInterruption() { +private fun Element.State.clearValuesBeforeInterruption() { offsetBeforeInterruption = Offset.Unspecified scaleBeforeInterruption = Scale.Unspecified alphaBeforeInterruption = Element.AlphaUnspecified @@ -655,13 +665,13 @@ private inline fun <T> computeInterruptedValue( */ private inline fun <T> setPlacementInterruptionDelta( element: Element, - sceneState: Element.SceneState, + stateInContent: Element.State, transition: TransitionState.Transition?, delta: T, - setter: (Element.SceneState, T) -> Unit, + setter: (Element.State, T) -> Unit, ) { - // Set the interruption delta on the current scene. - setter(sceneState, delta) + // Set the interruption delta on the current content. + setter(stateInContent, delta) if (transition == null) { return @@ -670,8 +680,9 @@ private inline fun <T> setPlacementInterruptionDelta( // If the element is shared, also set the delta on the other scene so that it is used by that // scene if we start overscrolling it and change the scene where the element is placed. val otherScene = - if (sceneState.scene == transition.fromScene) transition.toScene else transition.fromScene - val otherSceneState = element.sceneStates[otherScene] ?: return + if (stateInContent.content == transition.fromScene) transition.toScene + else transition.fromScene + val otherSceneState = element.stateByContent[otherScene] ?: return if (isSharedElementEnabled(element.key, transition)) { setter(otherSceneState, delta) } @@ -679,7 +690,7 @@ private inline fun <T> setPlacementInterruptionDelta( private fun shouldPlaceElement( layoutImpl: SceneTransitionLayoutImpl, - scene: SceneKey, + content: ContentKey, element: Element, transition: TransitionState.Transition?, ): Boolean { @@ -688,15 +699,16 @@ private fun shouldPlaceElement( return true } - // Don't place the element in this scene if this scene is not part of the current element + // Don't place the element in this content if this content is not part of the current element // transition. - if (scene != transition.fromScene && scene != transition.toScene) { + if (content != transition.fromScene && content != transition.toScene) { return false } // Place the element if it is not shared. if ( - transition.fromScene !in element.sceneStates || transition.toScene !in element.sceneStates + transition.fromScene !in element.stateByContent || + transition.toScene !in element.stateByContent ) { return true } @@ -708,7 +720,7 @@ private fun shouldPlaceElement( return shouldPlaceOrComposeSharedElement( layoutImpl, - scene, + content, element.key, transition, ) @@ -716,14 +728,14 @@ private fun shouldPlaceElement( internal fun shouldPlaceOrComposeSharedElement( layoutImpl: SceneTransitionLayoutImpl, - scene: SceneKey, + content: ContentKey, element: ElementKey, transition: TransitionState.Transition, ): Boolean { // If we are overscrolling, only place/compose the element in the overscrolling scene. val overscrollScene = transition.currentOverscrollSpec?.scene if (overscrollScene != null) { - return scene == overscrollScene + return content == overscrollScene } val scenePicker = element.scenePicker @@ -738,7 +750,7 @@ internal fun shouldPlaceOrComposeSharedElement( toSceneZIndex = layoutImpl.scenes.getValue(toScene).zIndex, ) ?: return false - return pickedScene == scene + return pickedScene == content } private fun isSharedElementEnabled( @@ -775,7 +787,7 @@ internal fun sharedElementTransformation( * placement and we don't want to read the transition progress in that phase. */ private fun isElementOpaque( - scene: Scene, + content: Content, element: Element, transition: TransitionState.Transition?, ): Boolean { @@ -785,8 +797,8 @@ private fun isElementOpaque( val fromScene = transition.fromScene val toScene = transition.toScene - val fromState = element.sceneStates[fromScene] - val toState = element.sceneStates[toScene] + val fromState = element.stateByContent[fromScene] + val toState = element.stateByContent[toScene] if (fromState == null && toState == null) { // TODO(b/311600838): Throw an exception instead once layers of disposed elements are not @@ -799,7 +811,7 @@ private fun isElementOpaque( return true } - return transition.transformationSpec.transformations(element.key, scene.key).alpha == null + return transition.transformationSpec.transformations(element.key, content.key).alpha == null } /** @@ -814,15 +826,15 @@ private fun elementAlpha( layoutImpl: SceneTransitionLayoutImpl, element: Element, transition: TransitionState.Transition?, - sceneState: Element.SceneState, + stateInContent: Element.State, ): Float { val alpha = computeValue( layoutImpl, - sceneState, + stateInContent, element, transition, - sceneValue = { 1f }, + contentValue = { 1f }, transformation = { it.alpha }, currentValue = { 1f }, isSpecified = { true }, @@ -832,12 +844,12 @@ private fun elementAlpha( // If the element is fading during this transition and that it is drawn for the first time, make // sure that it doesn't instantly appear on screen. - if (!element.wasDrawnInAnyScene && alpha > 0f) { - element.sceneStates.forEach { it.value.alphaBeforeInterruption = 0f } + if (!element.wasDrawnInAnyContent && alpha > 0f) { + element.stateByContent.forEach { it.value.alphaBeforeInterruption = 0f } } - val interruptedAlpha = interruptedAlpha(layoutImpl, element, transition, sceneState, alpha) - sceneState.lastAlpha = interruptedAlpha + val interruptedAlpha = interruptedAlpha(layoutImpl, element, transition, stateInContent, alpha) + stateInContent.lastAlpha = interruptedAlpha return interruptedAlpha } @@ -845,7 +857,7 @@ private fun interruptedAlpha( layoutImpl: SceneTransitionLayoutImpl, element: Element, transition: TransitionState.Transition?, - sceneState: Element.SceneState, + stateInContent: Element.State, alpha: Float, ): Float { return computeInterruptedValue( @@ -854,16 +866,16 @@ private fun interruptedAlpha( value = alpha, unspecifiedValue = Element.AlphaUnspecified, zeroValue = 0f, - getValueBeforeInterruption = { sceneState.alphaBeforeInterruption }, - setValueBeforeInterruption = { sceneState.alphaBeforeInterruption = it }, - getInterruptionDelta = { sceneState.alphaInterruptionDelta }, + getValueBeforeInterruption = { stateInContent.alphaBeforeInterruption }, + setValueBeforeInterruption = { stateInContent.alphaBeforeInterruption = it }, + getInterruptionDelta = { stateInContent.alphaInterruptionDelta }, setInterruptionDelta = { delta -> setPlacementInterruptionDelta( element = element, - sceneState = sceneState, + stateInContent = stateInContent, transition = transition, delta = delta, - setter = { sceneState, delta -> sceneState.alphaInterruptionDelta = delta }, + setter = { stateInContent, delta -> stateInContent.alphaInterruptionDelta = delta }, ) }, diff = { a, b -> a - b }, @@ -875,7 +887,7 @@ private fun measure( layoutImpl: SceneTransitionLayoutImpl, element: Element, transition: TransitionState.Transition?, - sceneState: Element.SceneState, + stateInContent: Element.State, measurable: Measurable, constraints: Constraints, ): Placeable { @@ -887,10 +899,10 @@ private fun measure( val targetSize = computeValue( layoutImpl, - sceneState, + stateInContent, element, transition, - sceneValue = { it.targetSize }, + contentValue = { it.targetSize }, transformation = { it.size }, currentValue = { measurable.measure(constraints).also { maybePlaceable = it }.size() }, isSpecified = { it != Element.SizeUnspecified }, @@ -900,8 +912,8 @@ private fun measure( // The measurable was already measured, so we can't take interruptions into account here given // that we are not allowed to measure the same measurable twice. maybePlaceable?.let { placeable -> - sceneState.sizeBeforeInterruption = Element.SizeUnspecified - sceneState.sizeInterruptionDelta = IntSize.Zero + stateInContent.sizeBeforeInterruption = Element.SizeUnspecified + stateInContent.sizeInterruptionDelta = IntSize.Zero return placeable } @@ -912,10 +924,10 @@ private fun measure( value = targetSize, unspecifiedValue = Element.SizeUnspecified, zeroValue = IntSize.Zero, - getValueBeforeInterruption = { sceneState.sizeBeforeInterruption }, - setValueBeforeInterruption = { sceneState.sizeBeforeInterruption = it }, - getInterruptionDelta = { sceneState.sizeInterruptionDelta }, - setInterruptionDelta = { sceneState.sizeInterruptionDelta = it }, + getValueBeforeInterruption = { stateInContent.sizeBeforeInterruption }, + setValueBeforeInterruption = { stateInContent.sizeBeforeInterruption = it }, + getInterruptionDelta = { stateInContent.sizeInterruptionDelta }, + setInterruptionDelta = { stateInContent.sizeInterruptionDelta = it }, diff = { a, b -> IntSize(a.width - b.width, a.height - b.height) }, add = { a, b, bProgress -> IntSize( @@ -939,15 +951,15 @@ private fun ContentDrawScope.getDrawScale( layoutImpl: SceneTransitionLayoutImpl, element: Element, transition: TransitionState.Transition?, - sceneState: Element.SceneState, + stateInContent: Element.State, ): Scale { val scale = computeValue( layoutImpl, - sceneState, + stateInContent, element, transition, - sceneValue = { Scale.Default }, + contentValue = { Scale.Default }, transformation = { it.drawScale }, currentValue = { Scale.Default }, isSpecified = { true }, @@ -965,16 +977,18 @@ private fun ContentDrawScope.getDrawScale( value = scale, unspecifiedValue = Scale.Unspecified, zeroValue = Scale.Zero, - getValueBeforeInterruption = { sceneState.scaleBeforeInterruption }, - setValueBeforeInterruption = { sceneState.scaleBeforeInterruption = it }, - getInterruptionDelta = { sceneState.scaleInterruptionDelta }, + getValueBeforeInterruption = { stateInContent.scaleBeforeInterruption }, + setValueBeforeInterruption = { stateInContent.scaleBeforeInterruption = it }, + getInterruptionDelta = { stateInContent.scaleInterruptionDelta }, setInterruptionDelta = { delta -> setPlacementInterruptionDelta( element = element, - sceneState = sceneState, + stateInContent = stateInContent, transition = transition, delta = delta, - setter = { sceneState, delta -> sceneState.scaleInterruptionDelta = delta }, + setter = { stateInContent, delta -> + stateInContent.scaleInterruptionDelta = delta + }, ) }, diff = { a, b -> @@ -1003,7 +1017,7 @@ private fun ContentDrawScope.getDrawScale( } ) - sceneState.lastScale = interruptedScale + stateInContent.lastScale = interruptedScale return interruptedScale } @@ -1015,11 +1029,11 @@ private fun ContentDrawScope.getDrawScale( * Measurable. * * @param layoutImpl the [SceneTransitionLayoutImpl] associated to [element]. - * @param currentSceneState the scene state of the scene for which we are computing the value. Note - * that during interruptions, this could be the state of a scene that is neither + * @param currentContentState the content state of the content for which we are computing the value. + * Note that during interruptions, this could be the state of a content that is neither * [transition.toScene] nor [transition.fromScene]. * @param element the element being animated. - * @param sceneValue the value being animated. + * @param contentValue the value being animated. * @param transformation the transformation associated to the value being animated. * @param currentValue the value that would be used if it is not transformed. Note that this is * different than [idleValue] even if the value is not transformed directly because it could be @@ -1030,10 +1044,10 @@ private fun ContentDrawScope.getDrawScale( */ private inline fun <T> computeValue( layoutImpl: SceneTransitionLayoutImpl, - currentSceneState: Element.SceneState, + currentContentState: Element.State, element: Element, transition: TransitionState.Transition?, - sceneValue: (Element.SceneState) -> T, + contentValue: (Element.State) -> T, transformation: (ElementTransformations) -> PropertyTransformation<T>?, currentValue: () -> T, isSpecified: (T) -> Boolean, @@ -1050,16 +1064,16 @@ private inline fun <T> computeValue( val fromScene = transition.fromScene val toScene = transition.toScene - val fromState = element.sceneStates[fromScene] - val toState = element.sceneStates[toScene] + val fromState = element.stateByContent[fromScene] + val toState = element.stateByContent[toScene] if (fromState == null && toState == null) { // TODO(b/311600838): Throw an exception instead once layers of disposed elements are not // run anymore. - return sceneValue(currentSceneState) + return contentValue(currentContentState) } - val currentScene = currentSceneState.scene + val currentScene = currentContentState.content if (transition is TransitionState.HasOverscrollProperties) { val overscroll = transition.currentOverscrollSpec if (overscroll?.scene == currentScene) { @@ -1067,7 +1081,7 @@ private inline fun <T> computeValue( overscroll.transformationSpec.transformations(element.key, currentScene) val propertySpec = transformation(elementSpec) ?: return currentValue() val overscrollState = checkNotNull(if (currentScene == toScene) toState else fromState) - val idleValue = sceneValue(overscrollState) + val idleValue = contentValue(overscrollState) val targetValue = propertySpec.transform( layoutImpl, @@ -1102,8 +1116,8 @@ private inline fun <T> computeValue( // elements follow the finger direction. val isSharedElement = fromState != null && toState != null if (isSharedElement && isSharedElementEnabled(element.key, transition)) { - val start = sceneValue(fromState!!) - val end = sceneValue(toState!!) + val start = contentValue(fromState!!) + val end = contentValue(toState!!) // TODO(b/316901148): Remove checks to isSpecified() once the lookahead pass runs for all // nodes before the intermediate layout pass. @@ -1117,7 +1131,7 @@ private inline fun <T> computeValue( // Get the transformed value, i.e. the target value at the beginning (for entering elements) or // end (for leaving elements) of the transition. - val sceneState = + val contentState = checkNotNull( when { isSharedElement && currentScene == fromScene -> fromState @@ -1129,26 +1143,26 @@ private inline fun <T> computeValue( // The scene for which we compute the transformation. Note that this is not necessarily // [currentScene] because [currentScene] could be a different scene than the transition // fromScene or toScene during interruptions. - val scene = sceneState.scene + val content = contentState.content val transformation = - transformation(transition.transformationSpec.transformations(element.key, scene)) + transformation(transition.transformationSpec.transformations(element.key, content)) val previewTransformation = transition.previewTransformationSpec?.let { - transformation(it.transformations(element.key, scene)) + transformation(it.transformations(element.key, content)) } if (previewTransformation != null) { val isInPreviewStage = transition.isInPreviewStage - val idleValue = sceneValue(sceneState) - val isEntering = scene == toScene + val idleValue = contentValue(contentState) + val isEntering = content == toScene val previewTargetValue = previewTransformation.transform( layoutImpl, - scene, + content, element, - sceneState, + contentState, transition, idleValue, ) @@ -1156,9 +1170,9 @@ private inline fun <T> computeValue( val targetValueOrNull = transformation?.transform( layoutImpl, - scene, + content, element, - sceneState, + contentState, transition, idleValue, ) @@ -1226,13 +1240,13 @@ private inline fun <T> computeValue( return currentValue() } - val idleValue = sceneValue(sceneState) + val idleValue = contentValue(contentState) val targetValue = transformation.transform( layoutImpl, - scene, + content, element, - sceneState, + contentState, transition, idleValue, ) @@ -1248,7 +1262,7 @@ private inline fun <T> computeValue( val rangeProgress = transformation.range?.progress(progress) ?: progress // Interpolate between the value at rest and the value before entering/after leaving. - val isEntering = scene == toScene + val isEntering = content == toScene return if (isEntering) { lerp(targetValue, idleValue, rangeProgress) } else { diff --git a/packages/SystemUI/compose/scene/src/com/android/compose/animation/scene/ElementMatcher.kt b/packages/SystemUI/compose/scene/src/com/android/compose/animation/scene/ElementMatcher.kt index 98dbb67d7c66..ca68c256fd73 100644 --- a/packages/SystemUI/compose/scene/src/com/android/compose/animation/scene/ElementMatcher.kt +++ b/packages/SystemUI/compose/scene/src/com/android/compose/animation/scene/ElementMatcher.kt @@ -18,20 +18,23 @@ package com.android.compose.animation.scene /** An interface to match one or more elements. */ interface ElementMatcher { - /** Whether the element with key [key] in scene [scene] matches this matcher. */ - fun matches(key: ElementKey, scene: SceneKey): Boolean + /** Whether the element with key [key] in scene [content] matches this matcher. */ + fun matches(key: ElementKey, content: ContentKey): Boolean } /** - * Returns an [ElementMatcher] that matches elements in [scene] also matching [this] + * Returns an [ElementMatcher] that matches elements in [content] also matching [this] * [ElementMatcher]. */ -fun ElementMatcher.inScene(scene: SceneKey): ElementMatcher { +fun ElementMatcher.inContent(content: ContentKey): ElementMatcher { val delegate = this - val matcherScene = scene + val matcherScene = content return object : ElementMatcher { - override fun matches(key: ElementKey, scene: SceneKey): Boolean { - return scene == matcherScene && delegate.matches(key, scene) + override fun matches(key: ElementKey, content: ContentKey): Boolean { + return content == matcherScene && delegate.matches(key, content) } } } + +@Deprecated("Use inContent() instead", replaceWith = ReplaceWith("inContent(scene)")) +fun ElementMatcher.inScene(scene: SceneKey) = inContent(scene) diff --git a/packages/SystemUI/compose/scene/src/com/android/compose/animation/scene/Key.kt b/packages/SystemUI/compose/scene/src/com/android/compose/animation/scene/Key.kt index 97703992cbf6..a9edf0afc66f 100644 --- a/packages/SystemUI/compose/scene/src/com/android/compose/animation/scene/Key.kt +++ b/packages/SystemUI/compose/scene/src/com/android/compose/animation/scene/Key.kt @@ -40,15 +40,20 @@ sealed class Key(val debugName: String, val identity: Any) { } } +/** The key for a content (scene or overlay). */ +sealed class ContentKey(debugName: String, identity: Any) : Key(debugName, identity) { + @VisibleForTesting + // TODO(b/240432457): Make internal once PlatformComposeSceneTransitionLayoutTestsUtils can + // access internal members. + abstract val testTag: String +} + /** Key for a scene. */ class SceneKey( debugName: String, identity: Any = Object(), -) : Key(debugName, identity) { - @VisibleForTesting - // TODO(b/240432457): Make internal once PlatformComposeSceneTransitionLayoutTestsUtils can - // access internal members. - val testTag: String = "scene:$debugName" +) : ContentKey(debugName, identity) { + override val testTag: String = "scene:$debugName" /** The unique [ElementKey] identifying this scene's root element. */ val rootElementKey = ElementKey(debugName, identity) @@ -74,7 +79,7 @@ class ElementKey( // access internal members. val testTag: String = "element:$debugName" - override fun matches(key: ElementKey, scene: SceneKey): Boolean { + override fun matches(key: ElementKey, content: ContentKey): Boolean { return key == this } @@ -86,7 +91,7 @@ class ElementKey( /** Matches any element whose [key identity][ElementKey.identity] matches [predicate]. */ fun withIdentity(predicate: (Any) -> Boolean): ElementMatcher { return object : ElementMatcher { - override fun matches(key: ElementKey, scene: SceneKey): Boolean { + override fun matches(key: ElementKey, content: ContentKey): Boolean { return predicate(key.identity) } } diff --git a/packages/SystemUI/compose/scene/src/com/android/compose/animation/scene/MovableElement.kt b/packages/SystemUI/compose/scene/src/com/android/compose/animation/scene/MovableElement.kt index 32eadde7bf30..e556f6f4ff05 100644 --- a/packages/SystemUI/compose/scene/src/com/android/compose/animation/scene/MovableElement.kt +++ b/packages/SystemUI/compose/scene/src/com/android/compose/animation/scene/MovableElement.kt @@ -27,21 +27,22 @@ import androidx.compose.ui.Modifier import androidx.compose.ui.layout.Layout import androidx.compose.ui.unit.IntSize import androidx.compose.ui.util.fastLastOrNull +import com.android.compose.animation.scene.content.Content @Composable internal fun Element( layoutImpl: SceneTransitionLayoutImpl, - scene: Scene, + sceneOrOverlay: Content, key: ElementKey, modifier: Modifier, content: @Composable ElementScope<ElementContentScope>.() -> Unit, ) { - Box(modifier.element(layoutImpl, scene, key)) { - val sceneScope = scene.scope + Box(modifier.element(layoutImpl, sceneOrOverlay, key)) { + val contentScope = sceneOrOverlay.scope val boxScope = this val elementScope = - remember(layoutImpl, key, scene, sceneScope, boxScope) { - ElementScopeImpl(layoutImpl, key, scene, sceneScope, boxScope) + remember(layoutImpl, key, sceneOrOverlay, contentScope, boxScope) { + ElementScopeImpl(layoutImpl, key, sceneOrOverlay, contentScope, boxScope) } content(elementScope) @@ -51,17 +52,17 @@ internal fun Element( @Composable internal fun MovableElement( layoutImpl: SceneTransitionLayoutImpl, - scene: Scene, + sceneOrOverlay: Content, key: ElementKey, modifier: Modifier, content: @Composable ElementScope<MovableElementContentScope>.() -> Unit, ) { - Box(modifier.element(layoutImpl, scene, key)) { - val sceneScope = scene.scope + Box(modifier.element(layoutImpl, sceneOrOverlay, key)) { + val contentScope = sceneOrOverlay.scope val boxScope = this val elementScope = - remember(layoutImpl, key, scene, sceneScope, boxScope) { - MovableElementScopeImpl(layoutImpl, key, scene, sceneScope, boxScope) + remember(layoutImpl, key, sceneOrOverlay, contentScope, boxScope) { + MovableElementScopeImpl(layoutImpl, key, sceneOrOverlay, contentScope, boxScope) } content(elementScope) @@ -71,7 +72,7 @@ internal fun MovableElement( private abstract class BaseElementScope<ContentScope>( private val layoutImpl: SceneTransitionLayoutImpl, private val element: ElementKey, - private val scene: Scene, + private val sceneOrOverlay: Content, ) : ElementScope<ContentScope> { @Composable override fun <T> animateElementValueAsState( @@ -82,7 +83,7 @@ private abstract class BaseElementScope<ContentScope>( ): AnimatedState<T> { return animateSharedValueAsState( layoutImpl, - scene.key, + sceneOrOverlay.key, element, key, value, @@ -95,12 +96,12 @@ private abstract class BaseElementScope<ContentScope>( private class ElementScopeImpl( layoutImpl: SceneTransitionLayoutImpl, element: ElementKey, - scene: Scene, - private val sceneScope: SceneScope, + content: Content, + private val delegateContentScope: ContentScope, private val boxScope: BoxScope, -) : BaseElementScope<ElementContentScope>(layoutImpl, element, scene) { +) : BaseElementScope<ElementContentScope>(layoutImpl, element, content) { private val contentScope = - object : ElementContentScope, SceneScope by sceneScope, BoxScope by boxScope {} + object : ElementContentScope, ContentScope by delegateContentScope, BoxScope by boxScope {} @Composable override fun content(content: @Composable ElementContentScope.() -> Unit) { @@ -111,12 +112,15 @@ private class ElementScopeImpl( private class MovableElementScopeImpl( private val layoutImpl: SceneTransitionLayoutImpl, private val element: ElementKey, - private val scene: Scene, - private val sceneScope: BaseSceneScope, + private val content: Content, + private val baseContentScope: BaseContentScope, private val boxScope: BoxScope, -) : BaseElementScope<MovableElementContentScope>(layoutImpl, element, scene) { +) : BaseElementScope<MovableElementContentScope>(layoutImpl, element, content) { private val contentScope = - object : MovableElementContentScope, BaseSceneScope by sceneScope, BoxScope by boxScope {} + object : + MovableElementContentScope, + BaseContentScope by baseContentScope, + BoxScope by boxScope {} @Composable override fun content(content: @Composable MovableElementContentScope.() -> Unit) { @@ -126,9 +130,10 @@ private class MovableElementScopeImpl( // during the transition. // TODO(b/317026105): Use derivedStateOf only if the scene picker reads the progress in its // logic. + val contentKey = this@MovableElementScopeImpl.content.key val shouldComposeMovableElement by - remember(layoutImpl, scene.key, element) { - derivedStateOf { shouldComposeMovableElement(layoutImpl, scene.key, element) } + remember(layoutImpl, contentKey, element) { + derivedStateOf { shouldComposeMovableElement(layoutImpl, contentKey, element) } } if (shouldComposeMovableElement) { @@ -152,7 +157,7 @@ private class MovableElementScopeImpl( val size = placeholderContentSize( layoutImpl, - scene.key, + contentKey, layoutImpl.elements.getValue(element), ) layout(size.width, size.height) {} @@ -163,7 +168,7 @@ private class MovableElementScopeImpl( private fun shouldComposeMovableElement( layoutImpl: SceneTransitionLayoutImpl, - scene: SceneKey, + content: ContentKey, element: ElementKey, ): Boolean { val transitions = layoutImpl.state.currentTransitions @@ -171,7 +176,7 @@ private fun shouldComposeMovableElement( // If we are idle, there is only one [scene] that is composed so we can compose our // movable content here. We still check that [scene] is equal to the current idle scene, to // make sure we only compose it there. - return layoutImpl.state.transitionState.currentScene == scene + return layoutImpl.state.transitionState.currentScene == content } // The current transition for this element is the last transition in which either fromScene or @@ -189,7 +194,7 @@ private fun shouldComposeMovableElement( // Always compose movable elements in the scene picked by their scene picker. return shouldPlaceOrComposeSharedElement( layoutImpl, - scene, + content, element, transition, ) @@ -201,12 +206,12 @@ private fun shouldComposeMovableElement( */ private fun placeholderContentSize( layoutImpl: SceneTransitionLayoutImpl, - scene: SceneKey, + content: ContentKey, element: Element, ): IntSize { // If the content of the movable element was already composed in this scene before, use that // target size. - val targetValueInScene = element.sceneStates.getValue(scene).targetSize + val targetValueInScene = element.stateByContent.getValue(content).targetSize if (targetValueInScene != Element.SizeUnspecified) { return targetValueInScene } @@ -219,8 +224,9 @@ private fun placeholderContentSize( // doesn't change between scenes. // TODO(b/317026105): Provide a way to give a hint size/content for cases where this is not // true. - val otherScene = if (transition.fromScene == scene) transition.toScene else transition.fromScene - val targetValueInOtherScene = element.sceneStates[otherScene]?.targetSize + val otherScene = + if (transition.fromScene == content) transition.toScene else transition.fromScene + val targetValueInOtherScene = element.stateByContent[otherScene]?.targetSize if (targetValueInOtherScene != null && targetValueInOtherScene != Element.SizeUnspecified) { return targetValueInOtherScene } diff --git a/packages/SystemUI/compose/scene/src/com/android/compose/animation/scene/SceneTransitionLayout.kt b/packages/SystemUI/compose/scene/src/com/android/compose/animation/scene/SceneTransitionLayout.kt index 2fc4526b31f2..3401af827d4c 100644 --- a/packages/SystemUI/compose/scene/src/com/android/compose/animation/scene/SceneTransitionLayout.kt +++ b/packages/SystemUI/compose/scene/src/com/android/compose/animation/scene/SceneTransitionLayout.kt @@ -34,7 +34,6 @@ import androidx.compose.ui.unit.Dp import androidx.compose.ui.unit.IntOffset import androidx.compose.ui.unit.IntSize import androidx.compose.ui.unit.LayoutDirection -import com.android.compose.animation.scene.UserAction.Resolved /** * [SceneTransitionLayout] is a container that automatically animates its content whenever its state @@ -85,7 +84,7 @@ interface SceneTransitionLayoutScope { fun scene( key: SceneKey, userActions: Map<UserAction, UserActionResult> = emptyMap(), - content: @Composable SceneScope.() -> Unit, + content: @Composable ContentScope.() -> Unit, ) } @@ -118,25 +117,25 @@ interface ElementStateScope { @Stable @ElementDsl -interface BaseSceneScope : ElementStateScope { - /** The key of this scene. */ - val sceneKey: SceneKey +interface BaseContentScope : ElementStateScope { + /** The key of this content. */ + val contentKey: ContentKey - /** The state of the [SceneTransitionLayout] in which this scene is contained. */ + /** The state of the [SceneTransitionLayout] in which this content is contained. */ val layoutState: SceneTransitionLayoutState /** * Tag an element identified by [key]. * * Tagging an element will allow you to reference that element when defining transitions, so - * that the element can be transformed and animated when the scene transitions in or out. + * that the element can be transformed and animated when the content transitions in or out. * - * Additionally, this [key] will be used to detect elements that are shared between scenes to + * Additionally, this [key] will be used to detect elements that are shared between contents to * automatically interpolate their size and offset. If you need to animate shared element values - * (i.e. values associated to this element that change depending on which scene it is composed + * (i.e. values associated to this element that change depending on which content it is composed * in), use [Element] instead. * - * Note that shared elements tagged using this function will be duplicated in each scene they + * Note that shared elements tagged using this function will be duplicated in each content they * are part of, so any **internal** state (e.g. state created using `remember { * mutableStateOf(...) }`) will be lost. If you need to preserve internal state, you should use * [MovableElement] instead. @@ -150,7 +149,7 @@ interface BaseSceneScope : ElementStateScope { * Create an element identified by [key]. * * Similar to [element], this creates an element that will be automatically shared when present - * in multiple scenes and that can be transformed during transitions, the same way that + * in multiple contents and that can be transformed during transitions, the same way that * [element] does. * * The only difference with [element] is that the provided [ElementScope] allows you to @@ -177,7 +176,7 @@ interface BaseSceneScope : ElementStateScope { * Create a *movable* element identified by [key]. * * Similar to [Element], this creates an element that will be automatically shared when present - * in multiple scenes and that can be transformed during transitions, and you can also use the + * in multiple contents and that can be transformed during transitions, and you can also use the * provided [ElementScope] to [animate element values][ElementScope.animateElementValueAsState]. * * The important difference with [element] and [Element] is that this element @@ -232,24 +231,26 @@ interface BaseSceneScope : ElementStateScope { fun Modifier.noResizeDuringTransitions(): Modifier } +typealias SceneScope = ContentScope + @Stable @ElementDsl -interface SceneScope : BaseSceneScope { +interface ContentScope : BaseContentScope { /** - * Animate some value at the scene level. + * Animate some value at the content level. * * @param value the value of this shared value in the current scene. * @param key the key of this shared value. * @param type the [SharedValueType] of this animated value. * @param canOverflow whether this value can overflow past the values it is interpolated * between, for instance because the transition is animated using a bouncy spring. - * @see animateSceneIntAsState - * @see animateSceneFloatAsState - * @see animateSceneDpAsState - * @see animateSceneColorAsState + * @see animateContentIntAsState + * @see animateContentFloatAsState + * @see animateContentDpAsState + * @see animateContentColorAsState */ @Composable - fun <T> animateSceneValueAsState( + fun <T> animateContentValueAsState( value: T, key: ValueKey, type: SharedValueType<T, *>, @@ -259,7 +260,7 @@ interface SceneScope : BaseSceneScope { /** * The type of a shared value animated using [ElementScope.animateElementValueAsState] or - * [SceneScope.animateSceneValueAsState]. + * [ContentScope.animateContentValueAsState]. */ @Stable interface SharedValueType<T, Delta> { @@ -321,8 +322,9 @@ interface ElementScope<ContentScope> { * The exact same scope as [androidx.compose.foundation.layout.BoxScope]. * * We can't reuse BoxScope directly because of the @LayoutScopeMarker annotation on it, which would - * prevent us from calling Modifier.element() and other methods of [SceneScope] inside any Box {} in - * the [content][ElementScope.content] of a [SceneScope.Element] or a [SceneScope.MovableElement]. + * prevent us from calling Modifier.element() and other methods of [ContentScope] inside any Box {} + * in the [content][ElementScope.content] of a [ContentScope.Element] or a + * [ContentScope.MovableElement]. */ @Stable @ElementDsl @@ -335,16 +337,16 @@ interface ElementBoxScope { } /** The scope for "normal" (not movable) elements. */ -@Stable @ElementDsl interface ElementContentScope : SceneScope, ElementBoxScope +@Stable @ElementDsl interface ElementContentScope : ContentScope, ElementBoxScope /** * The scope for the content of movable elements. * - * Note that it extends [BaseSceneScope] and not [SceneScope] because movable elements should not - * call [SceneScope.animateSceneValueAsState], given that their content is not composed in all - * scenes. + * Note that it extends [BaseContentScope] and not [ContentScope] because movable elements should + * not call [ContentScope.animateContentValueAsState], given that their content is not composed in + * all scenes. */ -@Stable @ElementDsl interface MovableElementContentScope : BaseSceneScope, ElementBoxScope +@Stable @ElementDsl interface MovableElementContentScope : BaseContentScope, ElementBoxScope /** An action performed by the user. */ sealed class UserAction { diff --git a/packages/SystemUI/compose/scene/src/com/android/compose/animation/scene/SceneTransitionLayoutImpl.kt b/packages/SystemUI/compose/scene/src/com/android/compose/animation/scene/SceneTransitionLayoutImpl.kt index 32db0b7cd9fe..062d5533c539 100644 --- a/packages/SystemUI/compose/scene/src/com/android/compose/animation/scene/SceneTransitionLayoutImpl.kt +++ b/packages/SystemUI/compose/scene/src/com/android/compose/animation/scene/SceneTransitionLayoutImpl.kt @@ -36,6 +36,8 @@ import androidx.compose.ui.unit.IntSize import androidx.compose.ui.unit.LayoutDirection import androidx.compose.ui.util.fastForEach import androidx.compose.ui.util.fastForEachReversed +import com.android.compose.animation.scene.content.Content +import com.android.compose.animation.scene.content.Scene import com.android.compose.ui.util.lerp import kotlinx.coroutines.CoroutineScope @@ -84,7 +86,7 @@ internal class SceneTransitionLayoutImpl( /** * The different values of a shared value keyed by a a [ValueKey] and the different elements and - * scenes it is associated to. + * contents it is associated to. */ private var _sharedValues: MutableMap<ValueKey, MutableMap<ElementKey?, SharedValue<*, *>>>? = null @@ -149,6 +151,12 @@ internal class SceneTransitionLayoutImpl( return scenes[key] ?: error("Scene $key is not configured") } + internal fun content(key: ContentKey): Content { + return when (key) { + is SceneKey -> scene(key) + } + } + internal fun updateScenes( builder: SceneTransitionLayoutScope.() -> Unit, layoutDirection: LayoutDirection, @@ -164,7 +172,7 @@ internal class SceneTransitionLayoutImpl( override fun scene( key: SceneKey, userActions: Map<UserAction, UserActionResult>, - content: @Composable SceneScope.() -> Unit, + content: @Composable ContentScope.() -> Unit, ) { scenesToRemove.remove(key) diff --git a/packages/SystemUI/compose/scene/src/com/android/compose/animation/scene/SceneTransitions.kt b/packages/SystemUI/compose/scene/src/com/android/compose/animation/scene/SceneTransitions.kt index 06b093d0b5db..cfa4c70c8239 100644 --- a/packages/SystemUI/compose/scene/src/com/android/compose/animation/scene/SceneTransitions.kt +++ b/packages/SystemUI/compose/scene/src/com/android/compose/animation/scene/SceneTransitions.kt @@ -302,18 +302,18 @@ internal class TransformationSpecImpl( override val distance: UserActionDistance?, override val transformations: List<Transformation>, ) : TransformationSpec { - private val cache = mutableMapOf<ElementKey, MutableMap<SceneKey, ElementTransformations>>() + private val cache = mutableMapOf<ElementKey, MutableMap<ContentKey, ElementTransformations>>() - internal fun transformations(element: ElementKey, scene: SceneKey): ElementTransformations { + internal fun transformations(element: ElementKey, content: ContentKey): ElementTransformations { return cache .getOrPut(element) { mutableMapOf() } - .getOrPut(scene) { computeTransformations(element, scene) } + .getOrPut(content) { computeTransformations(element, content) } } /** Filter [transformations] to compute the [ElementTransformations] of [element]. */ private fun computeTransformations( element: ElementKey, - scene: SceneKey, + content: ContentKey, ): ElementTransformations { var shared: SharedElementTransformation? = null var offset: PropertyTransformation<Offset>? = null @@ -351,7 +351,7 @@ internal class TransformationSpecImpl( } transformations.fastForEach { transformation -> - if (!transformation.matcher.matches(element, scene)) { + if (!transformation.matcher.matches(element, content)) { return@fastForEach } diff --git a/packages/SystemUI/compose/scene/src/com/android/compose/animation/scene/SwipeToScene.kt b/packages/SystemUI/compose/scene/src/com/android/compose/animation/scene/SwipeToScene.kt index a2118b2ff5bb..f06214645144 100644 --- a/packages/SystemUI/compose/scene/src/com/android/compose/animation/scene/SwipeToScene.kt +++ b/packages/SystemUI/compose/scene/src/com/android/compose/animation/scene/SwipeToScene.kt @@ -31,6 +31,7 @@ import androidx.compose.ui.node.PointerInputModifierNode import androidx.compose.ui.node.TraversableNode import androidx.compose.ui.node.findNearestAncestor import androidx.compose.ui.unit.IntSize +import com.android.compose.animation.scene.content.Scene /** * Configures the swipeable behavior of a [SceneTransitionLayout] depending on the current state. diff --git a/packages/SystemUI/compose/scene/src/com/android/compose/animation/scene/TransitionDsl.kt b/packages/SystemUI/compose/scene/src/com/android/compose/animation/scene/TransitionDsl.kt index 3a87d4130cfb..06be86d8eaf7 100644 --- a/packages/SystemUI/compose/scene/src/com/android/compose/animation/scene/TransitionDsl.kt +++ b/packages/SystemUI/compose/scene/src/com/android/compose/animation/scene/TransitionDsl.kt @@ -239,10 +239,11 @@ interface ElementScenePicker { * should not be drawn or composed in neither [transition.fromScene] nor [transition.toScene], * return `null`. * - * Important: For [MovableElements][SceneScope.MovableElement], this scene picker will *always* - * be used during transitions to decide whether we should compose that element in a given scene - * or not. Therefore, you should make sure that the returned [SceneKey] contains the movable - * element, otherwise that element will not be composed in any scene during the transition. + * Important: For [MovableElements][ContentScope.MovableElement], this scene picker will + * *always* be used during transitions to decide whether we should compose that element in a + * given scene or not. Therefore, you should make sure that the returned [SceneKey] contains the + * movable element, otherwise that element will not be composed in any scene during the + * transition. */ fun sceneDuringTransition( element: ElementKey, diff --git a/packages/SystemUI/compose/scene/src/com/android/compose/animation/scene/UserActionDistanceScopeImpl.kt b/packages/SystemUI/compose/scene/src/com/android/compose/animation/scene/UserActionDistanceScopeImpl.kt index b7abb33c1242..0f668044112e 100644 --- a/packages/SystemUI/compose/scene/src/com/android/compose/animation/scene/UserActionDistanceScopeImpl.kt +++ b/packages/SystemUI/compose/scene/src/com/android/compose/animation/scene/UserActionDistanceScopeImpl.kt @@ -23,13 +23,13 @@ internal class ElementStateScopeImpl( private val layoutImpl: SceneTransitionLayoutImpl, ) : ElementStateScope { override fun ElementKey.targetSize(scene: SceneKey): IntSize? { - return layoutImpl.elements[this]?.sceneStates?.get(scene)?.targetSize.takeIf { + return layoutImpl.elements[this]?.stateByContent?.get(scene)?.targetSize.takeIf { it != Element.SizeUnspecified } } override fun ElementKey.targetOffset(scene: SceneKey): Offset? { - return layoutImpl.elements[this]?.sceneStates?.get(scene)?.targetOffset.takeIf { + return layoutImpl.elements[this]?.stateByContent?.get(scene)?.targetOffset.takeIf { it != Offset.Unspecified } } diff --git a/packages/SystemUI/compose/scene/src/com/android/compose/animation/scene/Scene.kt b/packages/SystemUI/compose/scene/src/com/android/compose/animation/scene/content/Content.kt index a49f1af97183..492d2115cfdc 100644 --- a/packages/SystemUI/compose/scene/src/com/android/compose/animation/scene/Scene.kt +++ b/packages/SystemUI/compose/scene/src/com/android/compose/animation/scene/content/Content.kt @@ -1,5 +1,5 @@ /* - * Copyright 2023 The Android Open Source Project + * Copyright (C) 2024 The Android Open Source Project * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -14,7 +14,7 @@ * limitations under the License. */ -package com.android.compose.animation.scene +package com.android.compose.animation.scene.content import androidx.compose.foundation.gestures.Orientation import androidx.compose.foundation.layout.Box @@ -29,24 +29,44 @@ import androidx.compose.ui.layout.approachLayout import androidx.compose.ui.platform.testTag import androidx.compose.ui.unit.IntSize import androidx.compose.ui.zIndex +import com.android.compose.animation.scene.AnimatedState +import com.android.compose.animation.scene.ContentKey +import com.android.compose.animation.scene.ContentScope +import com.android.compose.animation.scene.Element +import com.android.compose.animation.scene.ElementContentScope +import com.android.compose.animation.scene.ElementKey +import com.android.compose.animation.scene.ElementScope +import com.android.compose.animation.scene.ElementStateScope +import com.android.compose.animation.scene.MovableElement +import com.android.compose.animation.scene.MovableElementContentScope +import com.android.compose.animation.scene.NestedScrollBehavior +import com.android.compose.animation.scene.SceneTransitionLayoutImpl +import com.android.compose.animation.scene.SceneTransitionLayoutState +import com.android.compose.animation.scene.SharedValueType +import com.android.compose.animation.scene.UserAction +import com.android.compose.animation.scene.UserActionResult +import com.android.compose.animation.scene.ValueKey +import com.android.compose.animation.scene.animateSharedValueAsState +import com.android.compose.animation.scene.element import com.android.compose.animation.scene.modifiers.noResizeDuringTransitions +import com.android.compose.animation.scene.nestedScrollToScene -/** A scene in a [SceneTransitionLayout]. */ +/** A content defined in a [SceneTransitionLayout], i.e. a scene or an overlay. */ @Stable -internal class Scene( - val key: SceneKey, - layoutImpl: SceneTransitionLayoutImpl, - content: @Composable SceneScope.() -> Unit, +internal sealed class Content( + open val key: ContentKey, + val layoutImpl: SceneTransitionLayoutImpl, + content: @Composable ContentScope.() -> Unit, actions: Map<UserAction.Resolved, UserActionResult>, zIndex: Float, ) { - internal val scope = SceneScopeImpl(layoutImpl, this) + internal val scope = ContentScopeImpl(layoutImpl, content = this) var content by mutableStateOf(content) - private var _userActions by mutableStateOf(checkValid(actions)) var zIndex by mutableFloatStateOf(zIndex) var targetSize by mutableStateOf(IntSize.Zero) + private var _userActions by mutableStateOf(checkValid(actions)) var userActions get() = _userActions set(value) { @@ -59,8 +79,8 @@ internal class Scene( userActions.forEach { (action, result) -> if (key == result.toScene) { error( - "Transition to the same scene is not supported. Scene $key, action $action," + - " result $result" + "Transition to the same content (scene/overlay) is not supported. Content " + + "$key, action $action, result $result" ) } } @@ -73,7 +93,7 @@ internal class Scene( modifier .zIndex(zIndex) .approachLayout( - isMeasurementApproachInProgress = { scope.layoutState.isTransitioning() } + isMeasurementApproachInProgress = { layoutImpl.state.isTransitioning() } ) { measurable, constraints -> targetSize = lookaheadSize val placeable = measurable.measure(constraints) @@ -84,21 +104,19 @@ internal class Scene( scope.content() } } - - override fun toString(): String { - return "Scene(key=$key)" - } } -internal class SceneScopeImpl( +internal class ContentScopeImpl( private val layoutImpl: SceneTransitionLayoutImpl, - private val scene: Scene, -) : SceneScope, ElementStateScope by layoutImpl.elementStateScope { - override val sceneKey: SceneKey = scene.key + private val content: Content, +) : ContentScope, ElementStateScope by layoutImpl.elementStateScope { + override val contentKey: ContentKey + get() = content.key + override val layoutState: SceneTransitionLayoutState = layoutImpl.state override fun Modifier.element(key: ElementKey): Modifier { - return element(layoutImpl, scene, key) + return element(layoutImpl, content, key) } @Composable @@ -107,7 +125,7 @@ internal class SceneScopeImpl( modifier: Modifier, content: @Composable (ElementScope<ElementContentScope>.() -> Unit) ) { - Element(layoutImpl, scene, key, modifier, content) + Element(layoutImpl, this@ContentScopeImpl.content, key, modifier, content) } @Composable @@ -116,19 +134,19 @@ internal class SceneScopeImpl( modifier: Modifier, content: @Composable (ElementScope<MovableElementContentScope>.() -> Unit) ) { - MovableElement(layoutImpl, scene, key, modifier, content) + MovableElement(layoutImpl, this@ContentScopeImpl.content, key, modifier, content) } @Composable - override fun <T> animateSceneValueAsState( + override fun <T> animateContentValueAsState( value: T, key: ValueKey, type: SharedValueType<T, *>, - canOverflow: Boolean + canOverflow: Boolean, ): AnimatedState<T> { return animateSharedValueAsState( layoutImpl = layoutImpl, - scene = scene.key, + content = content.key, element = null, key = key, value = value, @@ -141,27 +159,29 @@ internal class SceneScopeImpl( leftBehavior: NestedScrollBehavior, rightBehavior: NestedScrollBehavior, isExternalOverscrollGesture: () -> Boolean, - ): Modifier = - nestedScrollToScene( + ): Modifier { + return nestedScrollToScene( layoutImpl = layoutImpl, orientation = Orientation.Horizontal, topOrLeftBehavior = leftBehavior, bottomOrRightBehavior = rightBehavior, isExternalOverscrollGesture = isExternalOverscrollGesture, ) + } override fun Modifier.verticalNestedScrollToScene( topBehavior: NestedScrollBehavior, bottomBehavior: NestedScrollBehavior, isExternalOverscrollGesture: () -> Boolean, - ): Modifier = - nestedScrollToScene( + ): Modifier { + return nestedScrollToScene( layoutImpl = layoutImpl, orientation = Orientation.Vertical, topOrLeftBehavior = topBehavior, bottomOrRightBehavior = bottomBehavior, isExternalOverscrollGesture = isExternalOverscrollGesture, ) + } override fun Modifier.noResizeDuringTransitions(): Modifier { return noResizeDuringTransitions(layoutState = layoutImpl.state) diff --git a/packages/SystemUI/compose/scene/src/com/android/compose/animation/scene/content/Scene.kt b/packages/SystemUI/compose/scene/src/com/android/compose/animation/scene/content/Scene.kt new file mode 100644 index 000000000000..4a7a94d6e177 --- /dev/null +++ b/packages/SystemUI/compose/scene/src/com/android/compose/animation/scene/content/Scene.kt @@ -0,0 +1,39 @@ +/* + * Copyright (C) 2024 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.android.compose.animation.scene.content + +import androidx.compose.runtime.Composable +import androidx.compose.runtime.Stable +import com.android.compose.animation.scene.ContentScope +import com.android.compose.animation.scene.SceneKey +import com.android.compose.animation.scene.SceneTransitionLayoutImpl +import com.android.compose.animation.scene.UserAction +import com.android.compose.animation.scene.UserActionResult + +/** A scene defined in a [SceneTransitionLayout]. */ +@Stable +internal class Scene( + override val key: SceneKey, + layoutImpl: SceneTransitionLayoutImpl, + content: @Composable ContentScope.() -> Unit, + actions: Map<UserAction.Resolved, UserActionResult>, + zIndex: Float, +) : Content(key, layoutImpl, content, actions, zIndex) { + override fun toString(): String { + return "Scene(key=$key)" + } +} diff --git a/packages/SystemUI/compose/scene/src/com/android/compose/animation/scene/transformation/AnchoredSize.kt b/packages/SystemUI/compose/scene/src/com/android/compose/animation/scene/transformation/AnchoredSize.kt index 73ee4512c31f..65d4d2da4dd1 100644 --- a/packages/SystemUI/compose/scene/src/com/android/compose/animation/scene/transformation/AnchoredSize.kt +++ b/packages/SystemUI/compose/scene/src/com/android/compose/animation/scene/transformation/AnchoredSize.kt @@ -17,6 +17,7 @@ package com.android.compose.animation.scene.transformation import androidx.compose.ui.unit.IntSize +import com.android.compose.animation.scene.ContentKey import com.android.compose.animation.scene.Element import com.android.compose.animation.scene.ElementKey import com.android.compose.animation.scene.ElementMatcher @@ -33,15 +34,15 @@ internal class AnchoredSize( ) : PropertyTransformation<IntSize> { override fun transform( layoutImpl: SceneTransitionLayoutImpl, - scene: SceneKey, + content: ContentKey, element: Element, - sceneState: Element.SceneState, + sceneState: Element.State, transition: TransitionState.Transition, value: IntSize, ): IntSize { fun anchorSizeIn(scene: SceneKey): IntSize { val size = - layoutImpl.elements[anchor]?.sceneStates?.get(scene)?.targetSize?.takeIf { + layoutImpl.elements[anchor]?.stateByContent?.get(scene)?.targetSize?.takeIf { it != Element.SizeUnspecified } ?: throwMissingAnchorException( @@ -59,7 +60,7 @@ internal class AnchoredSize( // This simple implementation assumes that the size of [element] is the same as the size of // the [anchor] in [scene], so simply transform to the size of the anchor in the other // scene. - return if (scene == transition.fromScene) { + return if (content == transition.fromScene) { anchorSizeIn(transition.toScene) } else { anchorSizeIn(transition.fromScene) diff --git a/packages/SystemUI/compose/scene/src/com/android/compose/animation/scene/transformation/AnchoredTranslate.kt b/packages/SystemUI/compose/scene/src/com/android/compose/animation/scene/transformation/AnchoredTranslate.kt index 70dca4c065d3..8d7e1c971acf 100644 --- a/packages/SystemUI/compose/scene/src/com/android/compose/animation/scene/transformation/AnchoredTranslate.kt +++ b/packages/SystemUI/compose/scene/src/com/android/compose/animation/scene/transformation/AnchoredTranslate.kt @@ -18,6 +18,7 @@ package com.android.compose.animation.scene.transformation import androidx.compose.ui.geometry.Offset import androidx.compose.ui.geometry.isSpecified +import com.android.compose.animation.scene.ContentKey import com.android.compose.animation.scene.Element import com.android.compose.animation.scene.ElementKey import com.android.compose.animation.scene.ElementMatcher @@ -32,9 +33,9 @@ internal class AnchoredTranslate( ) : PropertyTransformation<Offset> { override fun transform( layoutImpl: SceneTransitionLayoutImpl, - scene: SceneKey, + content: ContentKey, element: Element, - sceneState: Element.SceneState, + sceneState: Element.State, transition: TransitionState.Transition, value: Offset, ): Offset { @@ -48,7 +49,7 @@ internal class AnchoredTranslate( val anchor = layoutImpl.elements[anchor] ?: throwException(scene = null) fun anchorOffsetIn(scene: SceneKey): Offset? { - return anchor.sceneStates[scene]?.targetOffset?.takeIf { it.isSpecified } + return anchor.stateByContent[scene]?.targetOffset?.takeIf { it.isSpecified } } // [element] will move the same amount as [anchor] does. @@ -60,7 +61,7 @@ internal class AnchoredTranslate( anchorOffsetIn(transition.toScene) ?: throwException(transition.toScene) val offset = anchorToOffset - anchorFromOffset - return if (scene == transition.toScene) { + return if (content == transition.toScene) { Offset( value.x - offset.x, value.y - offset.y, diff --git a/packages/SystemUI/compose/scene/src/com/android/compose/animation/scene/transformation/DrawScale.kt b/packages/SystemUI/compose/scene/src/com/android/compose/animation/scene/transformation/DrawScale.kt index 98c2dd3dc1cc..f010c3b1d3b4 100644 --- a/packages/SystemUI/compose/scene/src/com/android/compose/animation/scene/transformation/DrawScale.kt +++ b/packages/SystemUI/compose/scene/src/com/android/compose/animation/scene/transformation/DrawScale.kt @@ -17,10 +17,10 @@ package com.android.compose.animation.scene.transformation import androidx.compose.ui.geometry.Offset +import com.android.compose.animation.scene.ContentKey import com.android.compose.animation.scene.Element import com.android.compose.animation.scene.ElementMatcher import com.android.compose.animation.scene.Scale -import com.android.compose.animation.scene.SceneKey import com.android.compose.animation.scene.SceneTransitionLayoutImpl import com.android.compose.animation.scene.TransitionState @@ -37,9 +37,9 @@ internal class DrawScale( override fun transform( layoutImpl: SceneTransitionLayoutImpl, - scene: SceneKey, + content: ContentKey, element: Element, - sceneState: Element.SceneState, + sceneState: Element.State, transition: TransitionState.Transition, value: Scale, ): Scale { diff --git a/packages/SystemUI/compose/scene/src/com/android/compose/animation/scene/transformation/EdgeTranslate.kt b/packages/SystemUI/compose/scene/src/com/android/compose/animation/scene/transformation/EdgeTranslate.kt index 7daefd0d5d77..dfce997ba190 100644 --- a/packages/SystemUI/compose/scene/src/com/android/compose/animation/scene/transformation/EdgeTranslate.kt +++ b/packages/SystemUI/compose/scene/src/com/android/compose/animation/scene/transformation/EdgeTranslate.kt @@ -17,10 +17,10 @@ package com.android.compose.animation.scene.transformation import androidx.compose.ui.geometry.Offset +import com.android.compose.animation.scene.ContentKey import com.android.compose.animation.scene.Edge import com.android.compose.animation.scene.Element import com.android.compose.animation.scene.ElementMatcher -import com.android.compose.animation.scene.SceneKey import com.android.compose.animation.scene.SceneTransitionLayoutImpl import com.android.compose.animation.scene.TransitionState @@ -32,13 +32,13 @@ internal class EdgeTranslate( ) : PropertyTransformation<Offset> { override fun transform( layoutImpl: SceneTransitionLayoutImpl, - scene: SceneKey, + content: ContentKey, element: Element, - sceneState: Element.SceneState, + sceneState: Element.State, transition: TransitionState.Transition, value: Offset ): Offset { - val sceneSize = layoutImpl.scene(scene).targetSize + val sceneSize = layoutImpl.content(content).targetSize val elementSize = sceneState.targetSize if (elementSize == Element.SizeUnspecified) { return value diff --git a/packages/SystemUI/compose/scene/src/com/android/compose/animation/scene/transformation/Fade.kt b/packages/SystemUI/compose/scene/src/com/android/compose/animation/scene/transformation/Fade.kt index ada814e04ab2..c1bb017143a9 100644 --- a/packages/SystemUI/compose/scene/src/com/android/compose/animation/scene/transformation/Fade.kt +++ b/packages/SystemUI/compose/scene/src/com/android/compose/animation/scene/transformation/Fade.kt @@ -16,9 +16,9 @@ package com.android.compose.animation.scene.transformation +import com.android.compose.animation.scene.ContentKey import com.android.compose.animation.scene.Element import com.android.compose.animation.scene.ElementMatcher -import com.android.compose.animation.scene.SceneKey import com.android.compose.animation.scene.SceneTransitionLayoutImpl import com.android.compose.animation.scene.TransitionState @@ -28,9 +28,9 @@ internal class Fade( ) : PropertyTransformation<Float> { override fun transform( layoutImpl: SceneTransitionLayoutImpl, - scene: SceneKey, + content: ContentKey, element: Element, - sceneState: Element.SceneState, + sceneState: Element.State, transition: TransitionState.Transition, value: Float ): Float { diff --git a/packages/SystemUI/compose/scene/src/com/android/compose/animation/scene/transformation/ScaleSize.kt b/packages/SystemUI/compose/scene/src/com/android/compose/animation/scene/transformation/ScaleSize.kt index dca8f8521f1a..5adbf7eb2614 100644 --- a/packages/SystemUI/compose/scene/src/com/android/compose/animation/scene/transformation/ScaleSize.kt +++ b/packages/SystemUI/compose/scene/src/com/android/compose/animation/scene/transformation/ScaleSize.kt @@ -17,9 +17,9 @@ package com.android.compose.animation.scene.transformation import androidx.compose.ui.unit.IntSize +import com.android.compose.animation.scene.ContentKey import com.android.compose.animation.scene.Element import com.android.compose.animation.scene.ElementMatcher -import com.android.compose.animation.scene.SceneKey import com.android.compose.animation.scene.SceneTransitionLayoutImpl import com.android.compose.animation.scene.TransitionState import kotlin.math.roundToInt @@ -35,9 +35,9 @@ internal class ScaleSize( ) : PropertyTransformation<IntSize> { override fun transform( layoutImpl: SceneTransitionLayoutImpl, - scene: SceneKey, + content: ContentKey, element: Element, - sceneState: Element.SceneState, + sceneState: Element.State, transition: TransitionState.Transition, value: IntSize, ): IntSize { diff --git a/packages/SystemUI/compose/scene/src/com/android/compose/animation/scene/transformation/Transformation.kt b/packages/SystemUI/compose/scene/src/com/android/compose/animation/scene/transformation/Transformation.kt index 7be9ce1e39fc..24b71944b6d0 100644 --- a/packages/SystemUI/compose/scene/src/com/android/compose/animation/scene/transformation/Transformation.kt +++ b/packages/SystemUI/compose/scene/src/com/android/compose/animation/scene/transformation/Transformation.kt @@ -19,9 +19,9 @@ package com.android.compose.animation.scene.transformation import androidx.compose.ui.util.fastCoerceAtLeast import androidx.compose.ui.util.fastCoerceAtMost import androidx.compose.ui.util.fastCoerceIn +import com.android.compose.animation.scene.ContentKey import com.android.compose.animation.scene.Element import com.android.compose.animation.scene.ElementMatcher -import com.android.compose.animation.scene.SceneKey import com.android.compose.animation.scene.SceneTransitionLayoutImpl import com.android.compose.animation.scene.TransitionState @@ -61,9 +61,9 @@ internal sealed interface PropertyTransformation<T> : Transformation { // to these internal classes. fun transform( layoutImpl: SceneTransitionLayoutImpl, - scene: SceneKey, + content: ContentKey, element: Element, - sceneState: Element.SceneState, + sceneState: Element.State, transition: TransitionState.Transition, value: T, ): T diff --git a/packages/SystemUI/compose/scene/src/com/android/compose/animation/scene/transformation/Translate.kt b/packages/SystemUI/compose/scene/src/com/android/compose/animation/scene/transformation/Translate.kt index f066511f68ab..123756ae4211 100644 --- a/packages/SystemUI/compose/scene/src/com/android/compose/animation/scene/transformation/Translate.kt +++ b/packages/SystemUI/compose/scene/src/com/android/compose/animation/scene/transformation/Translate.kt @@ -19,10 +19,10 @@ package com.android.compose.animation.scene.transformation import androidx.compose.ui.geometry.Offset import androidx.compose.ui.unit.Dp import androidx.compose.ui.unit.dp +import com.android.compose.animation.scene.ContentKey import com.android.compose.animation.scene.Element import com.android.compose.animation.scene.ElementMatcher import com.android.compose.animation.scene.OverscrollScope -import com.android.compose.animation.scene.SceneKey import com.android.compose.animation.scene.SceneTransitionLayoutImpl import com.android.compose.animation.scene.TransitionState @@ -33,9 +33,9 @@ internal class Translate( ) : PropertyTransformation<Offset> { override fun transform( layoutImpl: SceneTransitionLayoutImpl, - scene: SceneKey, + content: ContentKey, element: Element, - sceneState: Element.SceneState, + sceneState: Element.State, transition: TransitionState.Transition, value: Offset, ): Offset { @@ -55,9 +55,9 @@ internal class OverscrollTranslate( ) : PropertyTransformation<Offset> { override fun transform( layoutImpl: SceneTransitionLayoutImpl, - scene: SceneKey, + content: ContentKey, element: Element, - sceneState: Element.SceneState, + sceneState: Element.State, transition: TransitionState.Transition, value: Offset, ): Offset { diff --git a/packages/SystemUI/compose/scene/src/com/android/compose/nestedscroll/LargeTopAppBarNestedScrollConnection.kt b/packages/SystemUI/compose/scene/src/com/android/compose/nestedscroll/LargeTopAppBarNestedScrollConnection.kt index 8e35988832dc..ae3169b117ba 100644 --- a/packages/SystemUI/compose/scene/src/com/android/compose/nestedscroll/LargeTopAppBarNestedScrollConnection.kt +++ b/packages/SystemUI/compose/scene/src/com/android/compose/nestedscroll/LargeTopAppBarNestedScrollConnection.kt @@ -57,7 +57,7 @@ fun LargeTopAppBarNestedScrollConnection( minHeight() < currentHeight && currentHeight < maxHeight() }, canScrollOnFling = true, - onStart = { /* do nothing */}, + onStart = { /* do nothing */ }, onScroll = { offsetAvailable -> val currentHeight = height() val amountConsumed = diff --git a/packages/SystemUI/compose/scene/src/com/android/compose/nestedscroll/PriorityNestedScrollConnection.kt b/packages/SystemUI/compose/scene/src/com/android/compose/nestedscroll/PriorityNestedScrollConnection.kt index ac11d3040d67..228f7ba48d3e 100644 --- a/packages/SystemUI/compose/scene/src/com/android/compose/nestedscroll/PriorityNestedScrollConnection.kt +++ b/packages/SystemUI/compose/scene/src/com/android/compose/nestedscroll/PriorityNestedScrollConnection.kt @@ -38,7 +38,7 @@ class PriorityNestedScrollConnection( private val canStartPreScroll: (offsetAvailable: Offset, offsetBeforeStart: Offset) -> Boolean, private val canStartPostScroll: (offsetAvailable: Offset, offsetBeforeStart: Offset) -> Boolean, private val canStartPostFling: (velocityAvailable: Velocity) -> Boolean, - private val canContinueScroll: () -> Boolean, + private val canContinueScroll: (source: NestedScrollSource) -> Boolean, private val canScrollOnFling: Boolean, private val onStart: (offsetAvailable: Offset) -> Unit, private val onScroll: (offsetAvailable: Offset) -> Offset, @@ -61,7 +61,7 @@ class PriorityNestedScrollConnection( if ( isPriorityMode || - (source == NestedScrollSource.Fling && !canScrollOnFling) || + (source == NestedScrollSource.SideEffect && !canScrollOnFling) || !canStartPostScroll(available, offsetBeforeStart) ) { // The priority mode cannot start so we won't consume the available offset. @@ -73,7 +73,7 @@ class PriorityNestedScrollConnection( override fun onPreScroll(available: Offset, source: NestedScrollSource): Offset { if (!isPriorityMode) { - if (source != NestedScrollSource.Fling || canScrollOnFling) { + if (source == NestedScrollSource.UserInput || canScrollOnFling) { if (canStartPreScroll(available, offsetScrolledBeforePriorityMode)) { return onPriorityStart(available) } @@ -84,7 +84,7 @@ class PriorityNestedScrollConnection( return Offset.Zero } - if (!canContinueScroll()) { + if (!canContinueScroll(source)) { // Step 3a: We have lost priority and we no longer need to intercept scroll events. onPriorityStop(velocity = Velocity.Zero) @@ -170,7 +170,7 @@ fun PriorityNestedScrollConnection( canStartPreScroll: (offsetAvailable: Float, offsetBeforeStart: Float) -> Boolean, canStartPostScroll: (offsetAvailable: Float, offsetBeforeStart: Float) -> Boolean, canStartPostFling: (velocityAvailable: Float) -> Boolean, - canContinueScroll: () -> Boolean, + canContinueScroll: (source: NestedScrollSource) -> Boolean, canScrollOnFling: Boolean, onStart: (offsetAvailable: Float) -> Unit, onScroll: (offsetAvailable: Float) -> Float, diff --git a/packages/SystemUI/compose/scene/tests/src/com/android/compose/animation/scene/AnimatedSharedAsStateTest.kt b/packages/SystemUI/compose/scene/tests/src/com/android/compose/animation/scene/AnimatedSharedAsStateTest.kt index a7889e2fac58..0f33303dcd15 100644 --- a/packages/SystemUI/compose/scene/tests/src/com/android/compose/animation/scene/AnimatedSharedAsStateTest.kt +++ b/packages/SystemUI/compose/scene/tests/src/com/android/compose/animation/scene/AnimatedSharedAsStateTest.kt @@ -67,7 +67,7 @@ class AnimatedSharedAsStateTest { } @Composable - private fun SceneScope.Foo( + private fun ContentScope.Foo( targetValues: Values, onCurrentValueChanged: (Values) -> Unit, ) { @@ -87,7 +87,7 @@ class AnimatedSharedAsStateTest { } @Composable - private fun SceneScope.MovableFoo( + private fun ContentScope.MovableFoo( targetValues: Values, onCurrentValueChanged: (Values) -> Unit, ) { @@ -105,14 +105,14 @@ class AnimatedSharedAsStateTest { } @Composable - private fun SceneScope.SceneValues( + private fun ContentScope.SceneValues( targetValues: Values, onCurrentValueChanged: (Values) -> Unit, ) { - val int by animateSceneIntAsState(targetValues.int, key = TestValues.Value1) - val float by animateSceneFloatAsState(targetValues.float, key = TestValues.Value2) - val dp by animateSceneDpAsState(targetValues.dp, key = TestValues.Value3) - val color by animateSceneColorAsState(targetValues.color, key = TestValues.Value4) + val int by animateContentIntAsState(targetValues.int, key = TestValues.Value1) + val float by animateContentFloatAsState(targetValues.float, key = TestValues.Value2) + val dp by animateContentDpAsState(targetValues.dp, key = TestValues.Value3) + val color by animateContentColorAsState(targetValues.color, key = TestValues.Value4) LaunchedEffect(Unit) { snapshotFlow { Values(int, float, dp, color) }.collect(onCurrentValueChanged) @@ -292,7 +292,7 @@ class AnimatedSharedAsStateTest { fun readingAnimatedStateValueDuringCompositionThrows() { assertThrows(IllegalStateException::class.java) { rule.testTransition( - fromSceneContent = { animateSceneIntAsState(0, TestValues.Value1).value }, + fromSceneContent = { animateContentIntAsState(0, TestValues.Value1).value }, toSceneContent = {}, transition = {}, ) {} @@ -302,21 +302,21 @@ class AnimatedSharedAsStateTest { @Test fun readingAnimatedStateValueDuringCompositionIsStillPossible() { @Composable - fun SceneScope.SceneValuesDuringComposition( + fun ContentScope.SceneValuesDuringComposition( targetValues: Values, onCurrentValueChanged: (Values) -> Unit, ) { val int by - animateSceneIntAsState(targetValues.int, key = TestValues.Value1) + animateContentIntAsState(targetValues.int, key = TestValues.Value1) .unsafeCompositionState(targetValues.int) val float by - animateSceneFloatAsState(targetValues.float, key = TestValues.Value2) + animateContentFloatAsState(targetValues.float, key = TestValues.Value2) .unsafeCompositionState(targetValues.float) val dp by - animateSceneDpAsState(targetValues.dp, key = TestValues.Value3) + animateContentDpAsState(targetValues.dp, key = TestValues.Value3) .unsafeCompositionState(targetValues.dp) val color by - animateSceneColorAsState(targetValues.color, key = TestValues.Value4) + animateContentColorAsState(targetValues.color, key = TestValues.Value4) .unsafeCompositionState(targetValues.color) val values = Values(int, float, dp, color) @@ -397,14 +397,14 @@ class AnimatedSharedAsStateTest { val foo = ValueKey("foo") val bar = ValueKey("bar") - val lastValues = mutableMapOf<ValueKey, MutableMap<SceneKey, Float>>() + val lastValues = mutableMapOf<ValueKey, MutableMap<ContentKey, Float>>() @Composable - fun SceneScope.animateFloat(value: Float, key: ValueKey) { - val animatedValue = animateSceneFloatAsState(value, key) + fun ContentScope.animateFloat(value: Float, key: ValueKey) { + val animatedValue = animateContentFloatAsState(value, key) LaunchedEffect(animatedValue) { snapshotFlow { animatedValue.value } - .collect { lastValues.getOrPut(key) { mutableMapOf() }[sceneKey] = it } + .collect { lastValues.getOrPut(key) { mutableMapOf() }[contentKey] = it } } } @@ -458,13 +458,13 @@ class AnimatedSharedAsStateTest { } val key = ValueKey("foo") - val lastValues = mutableMapOf<SceneKey, Float>() + val lastValues = mutableMapOf<ContentKey, Float>() @Composable - fun SceneScope.animateFloat(value: Float, key: ValueKey) { - val animatedValue = animateSceneFloatAsState(value, key) + fun ContentScope.animateFloat(value: Float, key: ValueKey) { + val animatedValue = animateContentFloatAsState(value, key) LaunchedEffect(animatedValue) { - snapshotFlow { animatedValue.value }.collect { lastValues[sceneKey] = it } + snapshotFlow { animatedValue.value }.collect { lastValues[contentKey] = it } } } diff --git a/packages/SystemUI/compose/scene/tests/src/com/android/compose/animation/scene/ElementTest.kt b/packages/SystemUI/compose/scene/tests/src/com/android/compose/animation/scene/ElementTest.kt index 1d9e9b72cc33..329257e4be22 100644 --- a/packages/SystemUI/compose/scene/tests/src/com/android/compose/animation/scene/ElementTest.kt +++ b/packages/SystemUI/compose/scene/tests/src/com/android/compose/animation/scene/ElementTest.kt @@ -86,7 +86,7 @@ class ElementTest { @get:Rule val rule = createComposeRule() @Composable - private fun SceneScope.Element( + private fun ContentScope.Element( key: ElementKey, size: Dp, offset: Dp, @@ -380,7 +380,7 @@ class ElementTest { assertThat(layoutImpl.elements.keys).containsExactly(key) val element = layoutImpl.elements.getValue(key) - assertThat(element.sceneStates.keys).containsExactly(SceneB) + assertThat(element.stateByContent.keys).containsExactly(SceneB) // Scene C, state 0: the same element is reused. rule.runOnUiThread { state.setTargetScene(SceneC, coroutineScope) } @@ -389,13 +389,13 @@ class ElementTest { assertThat(layoutImpl.elements.keys).containsExactly(key) assertThat(layoutImpl.elements.getValue(key)).isSameInstanceAs(element) - assertThat(element.sceneStates.keys).containsExactly(SceneC) + assertThat(element.stateByContent.keys).containsExactly(SceneC) // Scene C, state 1: the element is removed from the map. sceneCState = 1 rule.waitForIdle() - assertThat(element.sceneStates).isEmpty() + assertThat(element.stateByContent).isEmpty() assertThat(layoutImpl.elements).isEmpty() } @@ -405,7 +405,7 @@ class ElementTest { assertThrows(IllegalStateException::class.java) { rule.setContent { - TestSceneScope { + TestContentScope { Column { Box(Modifier.element(key)) Box(Modifier.element(key)) @@ -421,7 +421,7 @@ class ElementTest { assertThrows(IllegalStateException::class.java) { rule.setContent { - TestSceneScope { + TestContentScope { Column { val childModifier = Modifier.element(key) Box(childModifier) @@ -439,7 +439,7 @@ class ElementTest { assertThrows(IllegalStateException::class.java) { var nElements by mutableStateOf(1) rule.setContent { - TestSceneScope { + TestContentScope { Column { val childModifier = Modifier.element(key) repeat(nElements) { Box(childModifier) } @@ -457,7 +457,7 @@ class ElementTest { assertThrows(IllegalStateException::class.java) { var key by mutableStateOf(TestElements.Foo) rule.setContent { - TestSceneScope { + TestContentScope { Column { Box(Modifier.element(key)) Box(Modifier.element(TestElements.Bar)) @@ -491,7 +491,7 @@ class ElementTest { // There is only Foo in the elements map. assertThat(layoutImpl.elements.keys).containsExactly(TestElements.Foo) val fooElement = layoutImpl.elements.getValue(TestElements.Foo) - assertThat(fooElement.sceneStates.keys).containsExactly(SceneA) + assertThat(fooElement.stateByContent.keys).containsExactly(SceneA) key = TestElements.Bar @@ -499,8 +499,8 @@ class ElementTest { rule.waitForIdle() assertThat(layoutImpl.elements.keys).containsExactly(TestElements.Bar) val barElement = layoutImpl.elements.getValue(TestElements.Bar) - assertThat(barElement.sceneStates.keys).containsExactly(SceneA) - assertThat(fooElement.sceneStates).isEmpty() + assertThat(barElement.stateByContent.keys).containsExactly(SceneA) + assertThat(fooElement.stateByContent).isEmpty() } @Test @@ -553,7 +553,7 @@ class ElementTest { // There is only Foo in the elements map. assertThat(layoutImpl.elements.keys).containsExactly(TestElements.Foo) val element = layoutImpl.elements.getValue(TestElements.Foo) - val sceneValues = element.sceneStates + val sceneValues = element.stateByContent assertThat(sceneValues.keys).containsExactly(SceneA) // Get the ElementModifier node that should be reused later on when coming back to this @@ -576,7 +576,7 @@ class ElementTest { assertThat(layoutImpl.elements.keys).containsExactly(TestElements.Foo) val newElement = layoutImpl.elements.getValue(TestElements.Foo) - val newSceneValues = newElement.sceneStates + val newSceneValues = newElement.stateByContent assertThat(newElement).isNotEqualTo(element) assertThat(newSceneValues).isNotEqualTo(sceneValues) assertThat(newSceneValues.keys).containsExactly(SceneA) @@ -677,7 +677,7 @@ class ElementTest { modifier = Modifier.size(layoutWidth, layoutHeight) ) { scene(key = SceneA, userActions = mapOf(Swipe.Down to SceneB)) { - animateSceneFloatAsState( + animateContentFloatAsState( value = animatedFloatRange.start, key = TestValues.Value1, false @@ -686,7 +686,7 @@ class ElementTest { } scene(SceneB) { val animatedFloat by - animateSceneFloatAsState( + animateContentFloatAsState( value = animatedFloatRange.endInclusive, key = TestValues.Value1, canOverflow = false @@ -1215,15 +1215,15 @@ class ElementTest { } val layoutSize = DpSize(200.dp, 100.dp) - val lastValues = mutableMapOf<SceneKey, Float>() + val lastValues = mutableMapOf<ContentKey, Float>() @Composable - fun SceneScope.Foo(size: Dp, value: Float, modifier: Modifier = Modifier) { - val sceneKey = this.sceneKey + fun ContentScope.Foo(size: Dp, value: Float, modifier: Modifier = Modifier) { + val contentKey = this.contentKey Element(TestElements.Foo, modifier.size(size)) { val animatedValue = animateElementFloatAsState(value, TestValues.Value1) LaunchedEffect(animatedValue) { - snapshotFlow { animatedValue.value }.collect { lastValues[sceneKey] = it } + snapshotFlow { animatedValue.value }.collect { lastValues[contentKey] = it } } } } @@ -1388,8 +1388,8 @@ class ElementTest { // The interruption values should be unspecified and deltas should be set to zero. val foo = layoutImpl.elements.getValue(TestElements.Foo) - assertThat(foo.sceneStates.keys).containsExactly(SceneC) - val stateInC = foo.sceneStates.getValue(SceneC) + assertThat(foo.stateByContent.keys).containsExactly(SceneC) + val stateInC = foo.stateByContent.getValue(SceneC) assertThat(stateInC.offsetBeforeInterruption).isEqualTo(Offset.Unspecified) assertThat(stateInC.sizeBeforeInterruption).isEqualTo(Element.SizeUnspecified) assertThat(stateInC.scaleBeforeInterruption).isEqualTo(Scale.Unspecified) @@ -1423,7 +1423,7 @@ class ElementTest { } @Composable - fun SceneScope.Foo(modifier: Modifier = Modifier) { + fun ContentScope.Foo(modifier: Modifier = Modifier) { Box(modifier.element(TestElements.Foo).size(fooSize)) } @@ -1542,8 +1542,8 @@ class ElementTest { assertThat(layoutImpl.elements).containsKey(TestElements.Foo) val foo = layoutImpl.elements.getValue(TestElements.Foo) - assertThat(foo.sceneStates).containsKey(SceneB) - val bState = foo.sceneStates.getValue(SceneB) + assertThat(foo.stateByContent).containsKey(SceneB) + val bState = foo.stateByContent.getValue(SceneB) assertThat(bState.targetSize).isNotEqualTo(Element.SizeUnspecified) assertThat(bState.targetOffset).isNotEqualTo(Offset.Unspecified) @@ -1583,9 +1583,9 @@ class ElementTest { rule.waitForIdle() val foo = checkNotNull(layoutImpl.elements[TestElements.Foo]) - assertThat(foo.sceneStates[SceneA]).isNull() + assertThat(foo.stateByContent[SceneA]).isNull() - val fooInB = foo.sceneStates[SceneB] + val fooInB = foo.stateByContent[SceneB] assertThat(fooInB).isNotNull() assertThat(fooInB!!.lastAlpha).isEqualTo(0.5f) @@ -1599,7 +1599,7 @@ class ElementTest { state.startTransition(transition(from = SceneB, to = SceneC, progress = { 0.3f })) } rule.waitForIdle() - val fooInC = foo.sceneStates[SceneC] + val fooInC = foo.stateByContent[SceneC] assertThat(fooInC).isNotNull() assertThat(fooInC!!.lastAlpha).isEqualTo(1f) assertThat(fooInB.lastAlpha).isEqualTo(Element.AlphaUnspecified) @@ -1645,7 +1645,7 @@ class ElementTest { rule.waitForIdle() // Alpha of Foo should be 0f at interruption progress 100%. - val fooInB = layoutImpl.elements.getValue(TestElements.Foo).sceneStates.getValue(SceneB) + val fooInB = layoutImpl.elements.getValue(TestElements.Foo).stateByContent.getValue(SceneB) assertThat(fooInB.lastAlpha).isEqualTo(0f) // Alpha of Foo should be 0.6f at interruption progress 0%. @@ -1673,7 +1673,7 @@ class ElementTest { } @Composable - fun SceneScope.Foo() { + fun ContentScope.Foo() { Box(Modifier.element(TestElements.Foo).size(10.dp)) } @@ -1724,7 +1724,7 @@ class ElementTest { val fooInB = "fooInB" @Composable - fun SceneScope.MovableFoo(text: String, modifier: Modifier = Modifier) { + fun ContentScope.MovableFoo(text: String, modifier: Modifier = Modifier) { MovableElement(TestElements.Foo, modifier) { content { Text(text) } } } @@ -1773,7 +1773,7 @@ class ElementTest { } @Composable - fun SceneScope.SceneWithFoo(offset: DpOffset, modifier: Modifier = Modifier) { + fun ContentScope.SceneWithFoo(offset: DpOffset, modifier: Modifier = Modifier) { Box(modifier.fillMaxSize()) { Box(Modifier.offset(offset.x, offset.y).element(TestElements.Foo).size(100.dp)) } @@ -1856,7 +1856,7 @@ class ElementTest { val state = rule.runOnIdle { MutableSceneTransitionLayoutStateImpl(SceneA) } @Composable - fun SceneScope.NestedFooBar() { + fun ContentScope.NestedFooBar() { Box(Modifier.element(TestElements.Foo)) { Box(Modifier.element(TestElements.Bar).size(10.dp)) } @@ -1881,13 +1881,13 @@ class ElementTest { val foo = layoutImpl.elements.getValue(TestElements.Foo) val bar = layoutImpl.elements.getValue(TestElements.Bar) - assertThat(foo.sceneStates).containsKey(SceneA) - assertThat(bar.sceneStates).containsKey(SceneA) - assertThat(foo.sceneStates).doesNotContainKey(SceneB) - assertThat(bar.sceneStates).doesNotContainKey(SceneB) + assertThat(foo.stateByContent).containsKey(SceneA) + assertThat(bar.stateByContent).containsKey(SceneA) + assertThat(foo.stateByContent).doesNotContainKey(SceneB) + assertThat(bar.stateByContent).doesNotContainKey(SceneB) - val fooInA = foo.sceneStates.getValue(SceneA) - val barInA = bar.sceneStates.getValue(SceneA) + val fooInA = foo.stateByContent.getValue(SceneA) + val barInA = bar.stateByContent.getValue(SceneA) assertThat(fooInA.lastOffset).isNotEqualTo(Offset.Unspecified) assertThat(fooInA.lastAlpha).isNotEqualTo(Element.AlphaUnspecified) assertThat(fooInA.lastScale).isNotEqualTo(Scale.Unspecified) @@ -1903,11 +1903,11 @@ class ElementTest { rule.onNode(isElement(TestElements.Foo, SceneB)).assertIsDisplayed() rule.onNode(isElement(TestElements.Bar, SceneB)).assertIsDisplayed() - assertThat(foo.sceneStates).containsKey(SceneB) - assertThat(bar.sceneStates).containsKey(SceneB) + assertThat(foo.stateByContent).containsKey(SceneB) + assertThat(bar.stateByContent).containsKey(SceneB) - val fooInB = foo.sceneStates.getValue(SceneB) - val barInB = bar.sceneStates.getValue(SceneB) + val fooInB = foo.stateByContent.getValue(SceneB) + val barInB = bar.stateByContent.getValue(SceneB) assertThat(fooInA.lastOffset).isEqualTo(Offset.Unspecified) assertThat(fooInA.lastAlpha).isEqualTo(Element.AlphaUnspecified) assertThat(fooInA.lastScale).isEqualTo(Scale.Unspecified) @@ -1938,8 +1938,8 @@ class ElementTest { } @Composable - fun SceneScope.Foo() { - Box(Modifier.testTag("fooParentIn${sceneKey.debugName}")) { + fun ContentScope.Foo() { + Box(Modifier.testTag("fooParentIn${contentKey.debugName}")) { Box(Modifier.element(TestElements.Foo).size(20.dp)) } } @@ -1973,7 +1973,7 @@ class ElementTest { val state = rule.runOnIdle { MutableSceneTransitionLayoutStateImpl(SceneA) } @Composable - fun SceneScope.Foo(offset: Dp) { + fun ContentScope.Foo(offset: Dp) { Box(Modifier.fillMaxSize()) { Box(Modifier.offset(offset, offset).element(TestElements.Foo).size(20.dp)) } @@ -2041,7 +2041,7 @@ class ElementTest { } @Composable - fun SceneScope.Foo() { + fun ContentScope.Foo() { Box(Modifier.element(TestElements.Foo).size(10.dp)) } @@ -2062,7 +2062,11 @@ class ElementTest { rule.waitForIdle() assertThat( - layoutImpl.elements.getValue(TestElements.Foo).sceneStates.getValue(SceneB).lastSize + layoutImpl.elements + .getValue(TestElements.Foo) + .stateByContent + .getValue(SceneB) + .lastSize ) .isEqualTo(Element.SizeUnspecified) } @@ -2078,8 +2082,8 @@ class ElementTest { // In A => B, Foo is not shared and first fades out from A then fades in // B. sharedElement(TestElements.Foo, enabled = false) - fractionRange(end = 0.5f) { fade(TestElements.Foo.inScene(SceneA)) } - fractionRange(start = 0.5f) { fade(TestElements.Foo.inScene(SceneB)) } + fractionRange(end = 0.5f) { fade(TestElements.Foo.inContent(SceneA)) } + fractionRange(start = 0.5f) { fade(TestElements.Foo.inContent(SceneB)) } } from(SceneB, to = SceneA) { @@ -2091,7 +2095,7 @@ class ElementTest { } @Composable - fun SceneScope.Foo(modifier: Modifier = Modifier) { + fun ContentScope.Foo(modifier: Modifier = Modifier) { Box(modifier.element(TestElements.Foo).size(10.dp)) } @@ -2149,7 +2153,7 @@ class ElementTest { val state = rule.runOnIdle { MutableSceneTransitionLayoutStateImpl(SceneA) } @Composable - fun SceneScope.Foo(modifier: Modifier = Modifier) { + fun ContentScope.Foo(modifier: Modifier = Modifier) { Box(modifier.element(TestElements.Foo).size(10.dp)) } @@ -2216,7 +2220,7 @@ class ElementTest { // verify that preview transition for exiting elements is halfway played from // current-scene-value -> preview-target-value - val exiting1InB = layoutImpl.elements.getValue(exiting1).sceneStates.getValue(SceneB) + val exiting1InB = layoutImpl.elements.getValue(exiting1).stateByContent.getValue(SceneB) // e.g. exiting1 is half scaled... assertThat(exiting1InB.lastScale).isEqualTo(Scale(0.9f, 0.9f, Offset.Unspecified)) // ...and exiting2 is halfway translated from 0.dp to 20.dp... @@ -2228,7 +2232,7 @@ class ElementTest { // verify that preview transition for entering elements is halfway played from // preview-target-value -> transition-target-value (or target-scene-value if no // transition-target-value defined). - val entering1InA = layoutImpl.elements.getValue(entering1).sceneStates.getValue(SceneA) + val entering1InA = layoutImpl.elements.getValue(entering1).stateByContent.getValue(SceneA) // e.g. entering1 is half scaled between 0f and 0.5f -> 0.25f... assertThat(entering1InA.lastScale).isEqualTo(Scale(0.25f, 0.25f, Offset.Unspecified)) // ...and entering2 is half way translated between 30.dp and 0.dp @@ -2272,7 +2276,7 @@ class ElementTest { // verify that exiting elements remain in the preview-end state if no further transition is // defined for them in the second stage - val exiting1InB = layoutImpl.elements.getValue(exiting1).sceneStates.getValue(SceneB) + val exiting1InB = layoutImpl.elements.getValue(exiting1).stateByContent.getValue(SceneB) // i.e. exiting1 remains half scaled assertThat(exiting1InB.lastScale).isEqualTo(Scale(0.9f, 0.9f, Offset.Unspecified)) // in case there is an additional transition defined for the second stage, verify that the @@ -2286,7 +2290,7 @@ class ElementTest { rule.onNode(isElement(exiting3)).assertSizeIsEqualTo(90.dp, 90.dp) // verify that entering elements animate seamlessly to their target state - val entering1InA = layoutImpl.elements.getValue(entering1).sceneStates.getValue(SceneA) + val entering1InA = layoutImpl.elements.getValue(entering1).stateByContent.getValue(SceneA) // e.g. entering1, which was scaled from 0f to 0.25f during the preview phase, should now be // half way scaled between 0.25f and its target-state of 1f -> 0.625f assertThat(entering1InA.lastScale).isEqualTo(Scale(0.625f, 0.625f, Offset.Unspecified)) @@ -2318,7 +2322,7 @@ class ElementTest { } @Composable - fun SceneScope.Foo(elementKey: ElementKey) { + fun ContentScope.Foo(elementKey: ElementKey) { Box(Modifier.element(elementKey).size(100.dp)) } diff --git a/packages/SystemUI/compose/scene/tests/src/com/android/compose/animation/scene/MovableElementTest.kt b/packages/SystemUI/compose/scene/tests/src/com/android/compose/animation/scene/MovableElementTest.kt index 9523896e5c00..821cc2927443 100644 --- a/packages/SystemUI/compose/scene/tests/src/com/android/compose/animation/scene/MovableElementTest.kt +++ b/packages/SystemUI/compose/scene/tests/src/com/android/compose/animation/scene/MovableElementTest.kt @@ -62,7 +62,7 @@ class MovableElementTest { } @Composable - private fun SceneScope.MovableCounter(key: ElementKey, modifier: Modifier) { + private fun ContentScope.MovableCounter(key: ElementKey, modifier: Modifier) { MovableElement(key, modifier) { content { Counter() } } } @@ -264,7 +264,7 @@ class MovableElementTest { @Test fun movableElementContentIsRecomposedIfContentParametersChange() { @Composable - fun SceneScope.MovableFoo(text: String, modifier: Modifier = Modifier) { + fun ContentScope.MovableFoo(text: String, modifier: Modifier = Modifier) { MovableElement(TestElements.Foo, modifier) { content { Text(text) } } } @@ -298,7 +298,7 @@ class MovableElementTest { @Test fun elementScopeExtendsBoxScope() { rule.setContent { - TestSceneScope { + TestContentScope { Element(TestElements.Foo, Modifier.size(200.dp)) { content { Box(Modifier.testTag("bottomEnd").align(Alignment.BottomEnd)) @@ -315,7 +315,7 @@ class MovableElementTest { @Test fun movableElementScopeExtendsBoxScope() { rule.setContent { - TestSceneScope { + TestContentScope { MovableElement(TestElements.Foo, Modifier.size(200.dp)) { content { Box(Modifier.testTag("bottomEnd").align(Alignment.BottomEnd)) diff --git a/packages/SystemUI/compose/scene/tests/src/com/android/compose/animation/scene/NestedScrollToSceneTest.kt b/packages/SystemUI/compose/scene/tests/src/com/android/compose/animation/scene/NestedScrollToSceneTest.kt index 311a58018840..9ebc42650d45 100644 --- a/packages/SystemUI/compose/scene/tests/src/com/android/compose/animation/scene/NestedScrollToSceneTest.kt +++ b/packages/SystemUI/compose/scene/tests/src/com/android/compose/animation/scene/NestedScrollToSceneTest.kt @@ -48,7 +48,7 @@ class NestedScrollToSceneTest { private val layoutHeight = 400.dp private fun setup2ScenesAndScrollTouchSlop( - modifierSceneA: @Composable SceneScope.() -> Modifier = { Modifier }, + modifierSceneA: @Composable ContentScope.() -> Modifier = { Modifier }, ): MutableSceneTransitionLayoutState { val state = rule.runOnUiThread { diff --git a/packages/SystemUI/compose/scene/tests/src/com/android/compose/animation/scene/SceneTransitionLayoutTest.kt b/packages/SystemUI/compose/scene/tests/src/com/android/compose/animation/scene/SceneTransitionLayoutTest.kt index 1ec10793363e..32f3bac5054e 100644 --- a/packages/SystemUI/compose/scene/tests/src/com/android/compose/animation/scene/SceneTransitionLayoutTest.kt +++ b/packages/SystemUI/compose/scene/tests/src/com/android/compose/animation/scene/SceneTransitionLayoutTest.kt @@ -129,7 +129,7 @@ class SceneTransitionLayoutTest { } @Composable - private fun SceneScope.SharedFoo(size: Dp, childOffset: Dp, modifier: Modifier = Modifier) { + private fun ContentScope.SharedFoo(size: Dp, childOffset: Dp, modifier: Modifier = Modifier) { Element(TestElements.Foo, modifier.size(size).background(Color.Red)) { // Offset the single child of Foo by some animated shared offset. val offset by animateElementDpAsState(childOffset, TestValues.Value1) @@ -479,14 +479,14 @@ class SceneTransitionLayoutTest { fun sceneKeyInScope() { val state = rule.runOnUiThread { MutableSceneTransitionLayoutState(SceneA) } - var keyInA: SceneKey? = null - var keyInB: SceneKey? = null - var keyInC: SceneKey? = null + var keyInA: ContentKey? = null + var keyInB: ContentKey? = null + var keyInC: ContentKey? = null rule.setContent { SceneTransitionLayout(state) { - scene(SceneA) { keyInA = sceneKey } - scene(SceneB) { keyInB = sceneKey } - scene(SceneC) { keyInC = sceneKey } + scene(SceneA) { keyInA = contentKey } + scene(SceneB) { keyInB = contentKey } + scene(SceneC) { keyInC = contentKey } } } diff --git a/packages/SystemUI/compose/scene/tests/src/com/android/compose/animation/scene/transformation/AnchoredSizeTest.kt b/packages/SystemUI/compose/scene/tests/src/com/android/compose/animation/scene/transformation/AnchoredSizeTest.kt index 6233608dfad0..c9f71da1691b 100644 --- a/packages/SystemUI/compose/scene/tests/src/com/android/compose/animation/scene/transformation/AnchoredSizeTest.kt +++ b/packages/SystemUI/compose/scene/tests/src/com/android/compose/animation/scene/transformation/AnchoredSizeTest.kt @@ -25,7 +25,7 @@ import androidx.compose.runtime.Composable import androidx.compose.ui.Modifier import androidx.compose.ui.unit.dp import androidx.test.ext.junit.runners.AndroidJUnit4 -import com.android.compose.animation.scene.SceneScope +import com.android.compose.animation.scene.ContentScope import com.android.compose.animation.scene.TestElements import com.android.compose.animation.scene.TransitionBuilder import com.android.compose.animation.scene.TransitionRecordingSpec @@ -108,8 +108,8 @@ class AnchoredSizeTest { } private fun assertBarSizeMatchesGolden( - fromSceneContent: @Composable SceneScope.() -> Unit, - toSceneContent: @Composable SceneScope.() -> Unit, + fromSceneContent: @Composable ContentScope.() -> Unit, + toSceneContent: @Composable ContentScope.() -> Unit, transition: TransitionBuilder.() -> Unit, ) { val recordingSpec = diff --git a/packages/SystemUI/compose/scene/tests/src/com/android/compose/animation/scene/transformation/SharedElementTest.kt b/packages/SystemUI/compose/scene/tests/src/com/android/compose/animation/scene/transformation/SharedElementTest.kt index 8001f418a12c..00acb137a833 100644 --- a/packages/SystemUI/compose/scene/tests/src/com/android/compose/animation/scene/transformation/SharedElementTest.kt +++ b/packages/SystemUI/compose/scene/tests/src/com/android/compose/animation/scene/transformation/SharedElementTest.kt @@ -31,7 +31,7 @@ import androidx.test.ext.junit.runners.AndroidJUnit4 import com.android.compose.animation.scene.Edge import com.android.compose.animation.scene.TestElements import com.android.compose.animation.scene.TestScenes -import com.android.compose.animation.scene.inScene +import com.android.compose.animation.scene.inContent import com.android.compose.animation.scene.testTransition import com.android.compose.test.assertSizeIsEqualTo import org.junit.Rule @@ -125,10 +125,10 @@ class SharedElementTest { sharedElement(TestElements.Foo, enabled = false) // In SceneA, Foo leaves to the left edge. - translate(TestElements.Foo.inScene(TestScenes.SceneA), Edge.Left) + translate(TestElements.Foo.inContent(TestScenes.SceneA), Edge.Left) // In SceneB, Foo comes from the bottom edge. - translate(TestElements.Foo.inScene(TestScenes.SceneB), Edge.Bottom) + translate(TestElements.Foo.inContent(TestScenes.SceneB), Edge.Bottom) }, ) { before { onElement(TestElements.Foo).assertPositionInRootIsEqualTo(10.dp, 50.dp) } diff --git a/packages/SystemUI/compose/scene/tests/utils/src/com/android/compose/animation/scene/TestSceneScope.kt b/packages/SystemUI/compose/scene/tests/utils/src/com/android/compose/animation/scene/TestContentScope.kt index fbd557f3cbb3..00adefb150c1 100644 --- a/packages/SystemUI/compose/scene/tests/utils/src/com/android/compose/animation/scene/TestSceneScope.kt +++ b/packages/SystemUI/compose/scene/tests/utils/src/com/android/compose/animation/scene/TestContentScope.kt @@ -20,11 +20,13 @@ import androidx.compose.runtime.Composable import androidx.compose.runtime.remember import androidx.compose.ui.Modifier -/** `SceneScope` for tests, which allows a single scene to be drawn in a [SceneTransitionLayout]. */ +/** + * [ContentScope] for tests, which allows a single scene to be drawn in a [SceneTransitionLayout]. + */ @Composable -fun TestSceneScope( +fun TestContentScope( modifier: Modifier = Modifier, - content: @Composable SceneScope.() -> Unit, + content: @Composable ContentScope.() -> Unit, ) { val currentScene = remember { SceneKey("current") } val state = remember { MutableSceneTransitionLayoutState(currentScene) } diff --git a/packages/SystemUI/compose/scene/tests/utils/src/com/android/compose/animation/scene/TestTransition.kt b/packages/SystemUI/compose/scene/tests/utils/src/com/android/compose/animation/scene/TestTransition.kt index a37d78ef8a71..7f26b9855a9a 100644 --- a/packages/SystemUI/compose/scene/tests/utils/src/com/android/compose/animation/scene/TestTransition.kt +++ b/packages/SystemUI/compose/scene/tests/utils/src/com/android/compose/animation/scene/TestTransition.kt @@ -18,9 +18,7 @@ package com.android.compose.animation.scene import androidx.compose.runtime.Composable import androidx.compose.runtime.LaunchedEffect -import androidx.compose.runtime.getValue import androidx.compose.runtime.rememberCoroutineScope -import androidx.compose.runtime.setValue import androidx.compose.ui.Modifier import androidx.compose.ui.semantics.SemanticsNode import androidx.compose.ui.test.SemanticsNodeInteraction @@ -87,8 +85,8 @@ interface TransitionTestAssertionScope { * @sample com.android.compose.animation.scene.transformation.TranslateTest */ fun ComposeContentTestRule.testTransition( - fromSceneContent: @Composable SceneScope.() -> Unit, - toSceneContent: @Composable SceneScope.() -> Unit, + fromSceneContent: @Composable ContentScope.() -> Unit, + toSceneContent: @Composable ContentScope.() -> Unit, transition: TransitionBuilder.() -> Unit, layoutModifier: Modifier = Modifier, fromScene: SceneKey = TestScenes.SceneA, @@ -134,8 +132,8 @@ fun TimeSeriesCaptureScope<SemanticsNodeInteractionsProvider>.featureOfElement( /** Records the transition between two scenes of [transitionLayout][SceneTransitionLayout]. */ fun MotionTestRule<ComposeToolkit>.recordTransition( - fromSceneContent: @Composable SceneScope.() -> Unit, - toSceneContent: @Composable SceneScope.() -> Unit, + fromSceneContent: @Composable ContentScope.() -> Unit, + toSceneContent: @Composable ContentScope.() -> Unit, transition: TransitionBuilder.() -> Unit, recordingSpec: TransitionRecordingSpec, layoutModifier: Modifier = Modifier, diff --git a/packages/SystemUI/customization/src/com/android/systemui/shared/notifications/data/repository/NotificationSettingsRepository.kt b/packages/SystemUI/customization/src/com/android/systemui/shared/notifications/data/repository/NotificationSettingsRepository.kt index 9e857deb280a..362e23dd9641 100644 --- a/packages/SystemUI/customization/src/com/android/systemui/shared/notifications/data/repository/NotificationSettingsRepository.kt +++ b/packages/SystemUI/customization/src/com/android/systemui/shared/notifications/data/repository/NotificationSettingsRepository.kt @@ -17,10 +17,13 @@ package com.android.systemui.shared.notifications.data.repository import android.provider.Settings +import android.provider.Settings.Secure.ZEN_DURATION_PROMPT import com.android.systemui.shared.settings.data.repository.SecureSettingsRepository +import com.android.systemui.shared.settings.data.repository.SystemSettingsRepository import kotlinx.coroutines.CoroutineDispatcher import kotlinx.coroutines.CoroutineScope import kotlinx.coroutines.flow.Flow +import kotlinx.coroutines.flow.SharingStarted import kotlinx.coroutines.flow.StateFlow import kotlinx.coroutines.flow.distinctUntilChanged import kotlinx.coroutines.flow.flowOn @@ -30,9 +33,10 @@ import kotlinx.coroutines.withContext /** Provides access to state related to notification settings. */ class NotificationSettingsRepository( - private val scope: CoroutineScope, + private val backgroundScope: CoroutineScope, private val backgroundDispatcher: CoroutineDispatcher, private val secureSettingsRepository: SecureSettingsRepository, + systemSettingsRepository: SystemSettingsRepository, ) { val isNotificationHistoryEnabled: Flow<Boolean> = secureSettingsRepository @@ -48,9 +52,7 @@ class NotificationSettingsRepository( ) .map { it == 1 } .flowOn(backgroundDispatcher) - .stateIn( - scope = scope, - ) + .stateIn(scope = backgroundScope) suspend fun setShowNotificationsOnLockscreenEnabled(enabled: Boolean) { withContext(backgroundDispatcher) { @@ -60,4 +62,27 @@ class NotificationSettingsRepository( ) } } + + val isCooldownEnabled: StateFlow<Boolean> = + systemSettingsRepository + .intSetting(name = Settings.System.NOTIFICATION_COOLDOWN_ENABLED) + .map { it == 1 } + .flowOn(backgroundDispatcher) + .stateIn( + scope = backgroundScope, + started = SharingStarted.Eagerly, + initialValue = false, + ) + + /** The default duration for DND mode when enabled. See [Settings.Secure.ZEN_DURATION]. */ + val zenDuration: StateFlow<Int> = + secureSettingsRepository + .intSetting(name = Settings.Secure.ZEN_DURATION) + .distinctUntilChanged() + .flowOn(backgroundDispatcher) + .stateIn( + backgroundScope, + started = SharingStarted.Eagerly, + initialValue = ZEN_DURATION_PROMPT, + ) } diff --git a/packages/SystemUI/customization/src/com/android/systemui/shared/notifications/domain/interactor/NotificationSettingsInteractor.kt b/packages/SystemUI/customization/src/com/android/systemui/shared/notifications/domain/interactor/NotificationSettingsInteractor.kt index b4105bdecc0a..a274f1d3a473 100644 --- a/packages/SystemUI/customization/src/com/android/systemui/shared/notifications/domain/interactor/NotificationSettingsInteractor.kt +++ b/packages/SystemUI/customization/src/com/android/systemui/shared/notifications/domain/interactor/NotificationSettingsInteractor.kt @@ -38,4 +38,5 @@ class NotificationSettingsInteractor( val current = repository.isShowNotificationsOnLockScreenEnabled().value repository.setShowNotificationsOnLockscreenEnabled(!current) } -} + + val isCooldownEnabled = repository.isCooldownEnabled} diff --git a/packages/SystemUI/customization/src/com/android/systemui/shared/settings/data/repository/SystemSettingsRepository.kt b/packages/SystemUI/customization/src/com/android/systemui/shared/settings/data/repository/SystemSettingsRepository.kt new file mode 100644 index 000000000000..afe82fb2a5fa --- /dev/null +++ b/packages/SystemUI/customization/src/com/android/systemui/shared/settings/data/repository/SystemSettingsRepository.kt @@ -0,0 +1,117 @@ +/* + * Copyright (C) 2024 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.android.systemui.shared.settings.data.repository + +import android.content.ContentResolver +import android.database.ContentObserver +import android.provider.Settings +import kotlinx.coroutines.CoroutineDispatcher +import kotlinx.coroutines.channels.awaitClose +import kotlinx.coroutines.flow.Flow +import kotlinx.coroutines.flow.callbackFlow +import kotlinx.coroutines.flow.flowOn +import kotlinx.coroutines.flow.map +import kotlinx.coroutines.withContext + +/** + * Defines interface for classes that can provide access to data from [Settings.System]. This + * repository doesn't guarantee to provide value across different users. For that see: + * [UserAwareSecureSettingsRepository] which does that for secure settings. + */ +interface SystemSettingsRepository { + + /** Returns a [Flow] tracking the value of a setting as an [Int]. */ + fun intSetting( + name: String, + defaultValue: Int = 0, + ): Flow<Int> + + /** Updates the value of the setting with the given name. */ + suspend fun setInt( + name: String, + value: Int, + ) + + suspend fun getInt( + name: String, + defaultValue: Int = 0, + ): Int + + suspend fun getString(name: String): String? +} + +class SystemSettingsRepositoryImpl( + private val contentResolver: ContentResolver, + private val backgroundDispatcher: CoroutineDispatcher, +) : SystemSettingsRepository { + + override fun intSetting( + name: String, + defaultValue: Int, + ): Flow<Int> { + return callbackFlow { + val observer = + object : ContentObserver(null) { + override fun onChange(selfChange: Boolean) { + trySend(Unit) + } + } + + contentResolver.registerContentObserver( + Settings.System.getUriFor(name), + /* notifyForDescendants= */ false, + observer, + ) + send(Unit) + + awaitClose { contentResolver.unregisterContentObserver(observer) } + } + .map { Settings.System.getInt(contentResolver, name, defaultValue) } + // The above work is done on the background thread (which is important for accessing + // settings through the content resolver). + .flowOn(backgroundDispatcher) + } + + override suspend fun setInt(name: String, value: Int) { + withContext(backgroundDispatcher) { + Settings.System.putInt( + contentResolver, + name, + value, + ) + } + } + + override suspend fun getInt(name: String, defaultValue: Int): Int { + return withContext(backgroundDispatcher) { + Settings.System.getInt( + contentResolver, + name, + defaultValue, + ) + } + } + + override suspend fun getString(name: String): String? { + return withContext(backgroundDispatcher) { + Settings.System.getString( + contentResolver, + name, + ) + } + } +} diff --git a/packages/SystemUI/customization/tests/utils/src/com/android/systemui/shared/settings/data/repository/FakeSystemSettingsRepository.kt b/packages/SystemUI/customization/tests/utils/src/com/android/systemui/shared/settings/data/repository/FakeSystemSettingsRepository.kt new file mode 100644 index 000000000000..7da2b40fd57a --- /dev/null +++ b/packages/SystemUI/customization/tests/utils/src/com/android/systemui/shared/settings/data/repository/FakeSystemSettingsRepository.kt @@ -0,0 +1,42 @@ +/* + * Copyright (C) 2024 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.android.systemui.shared.settings.data.repository + +import kotlinx.coroutines.flow.Flow +import kotlinx.coroutines.flow.MutableStateFlow +import kotlinx.coroutines.flow.map + +class FakeSystemSettingsRepository : SystemSettingsRepository { + + private val settings = MutableStateFlow<Map<String, String>>(mutableMapOf()) + + override fun intSetting(name: String, defaultValue: Int): Flow<Int> { + return settings.map { it.getOrDefault(name, defaultValue.toString()) }.map { it.toInt() } + } + + override suspend fun setInt(name: String, value: Int) { + settings.value = settings.value.toMutableMap().apply { this[name] = value.toString() } + } + + override suspend fun getInt(name: String, defaultValue: Int): Int { + return settings.value[name]?.toInt() ?: defaultValue + } + + override suspend fun getString(name: String): String? { + return settings.value[name] + } +} diff --git a/packages/SystemUI/multivalentTests/src/com/android/systemui/biometrics/UdfpsControllerOverlayTest.kt b/packages/SystemUI/multivalentTests/src/com/android/systemui/biometrics/UdfpsControllerOverlayTest.kt index 242e822664c0..e2a6a5508992 100644 --- a/packages/SystemUI/multivalentTests/src/com/android/systemui/biometrics/UdfpsControllerOverlayTest.kt +++ b/packages/SystemUI/multivalentTests/src/com/android/systemui/biometrics/UdfpsControllerOverlayTest.kt @@ -35,6 +35,8 @@ import android.view.WindowManager import android.view.accessibility.AccessibilityManager import androidx.test.ext.junit.runners.AndroidJUnit4 import androidx.test.filters.SmallTest +import com.android.app.viewcapture.ViewCapture +import com.android.app.viewcapture.ViewCaptureAwareWindowManager import com.android.keyguard.KeyguardUpdateMonitor import com.android.systemui.Flags import com.android.systemui.SysuiTestCase @@ -70,6 +72,7 @@ import com.android.systemui.statusbar.policy.KeyguardStateController import com.android.systemui.testKosmos import com.android.systemui.user.domain.interactor.SelectedUserInteractor import com.google.common.truth.Truth.assertThat +import dagger.Lazy import kotlinx.coroutines.ExperimentalCoroutinesApi import kotlinx.coroutines.test.TestScope import kotlinx.coroutines.test.runCurrent @@ -108,6 +111,7 @@ class UdfpsControllerOverlayTest : SysuiTestCase() { @Mock private lateinit var inflater: LayoutInflater @Mock private lateinit var windowManager: WindowManager + @Mock private lateinit var lazyViewCapture: kotlin.Lazy<ViewCapture> @Mock private lateinit var accessibilityManager: AccessibilityManager @Mock private lateinit var statusBarStateController: StatusBarStateController @Mock private lateinit var statusBarKeyguardViewManager: StatusBarKeyguardViewManager @@ -192,7 +196,8 @@ class UdfpsControllerOverlayTest : SysuiTestCase() { UdfpsControllerOverlay( context, inflater, - windowManager, + ViewCaptureAwareWindowManager(windowManager, lazyViewCapture, + isViewCaptureEnabled = false), accessibilityManager, statusBarStateController, statusBarKeyguardViewManager, diff --git a/packages/SystemUI/multivalentTests/src/com/android/systemui/biometrics/UdfpsControllerTest.java b/packages/SystemUI/multivalentTests/src/com/android/systemui/biometrics/UdfpsControllerTest.java index 54e0725957e6..d86890bf2369 100644 --- a/packages/SystemUI/multivalentTests/src/com/android/systemui/biometrics/UdfpsControllerTest.java +++ b/packages/SystemUI/multivalentTests/src/com/android/systemui/biometrics/UdfpsControllerTest.java @@ -65,12 +65,12 @@ import android.view.Surface; import android.view.View; import android.view.ViewGroup; import android.view.ViewRootImpl; -import android.view.WindowManager; import android.view.accessibility.AccessibilityManager; import androidx.test.ext.junit.runners.AndroidJUnit4; import androidx.test.filters.SmallTest; +import com.android.app.viewcapture.ViewCaptureAwareWindowManager; import com.android.internal.logging.InstanceIdSequence; import com.android.internal.util.LatencyTracker; import com.android.keyguard.KeyguardUpdateMonitor; @@ -87,6 +87,7 @@ import com.android.systemui.biometrics.ui.viewmodel.DefaultUdfpsTouchOverlayView import com.android.systemui.biometrics.ui.viewmodel.DeviceEntryUdfpsTouchOverlayViewModel; import com.android.systemui.bouncer.domain.interactor.AlternateBouncerInteractor; import com.android.systemui.bouncer.domain.interactor.PrimaryBouncerInteractor; +import com.android.systemui.camera.CameraGestureHelper; import com.android.systemui.classifier.FalsingCollector; import com.android.systemui.deviceentry.domain.interactor.DeviceEntryFaceAuthInteractor; import com.android.systemui.dump.DumpManager; @@ -118,6 +119,8 @@ import com.android.systemui.util.time.SystemClock; import dagger.Lazy; +import javax.inject.Provider; + import kotlinx.coroutines.CoroutineScope; import org.junit.Before; @@ -152,7 +155,7 @@ public class UdfpsControllerTest extends SysuiTestCase { @Mock private FingerprintManager mFingerprintManager; @Mock - private WindowManager mWindowManager; + private ViewCaptureAwareWindowManager mWindowManager; @Mock private StatusBarStateController mStatusBarStateController; @Mock @@ -261,6 +264,8 @@ public class UdfpsControllerTest extends SysuiTestCase { private Lazy<DeviceEntryUdfpsTouchOverlayViewModel> mDeviceEntryUdfpsTouchOverlayViewModel; @Mock private Lazy<DefaultUdfpsTouchOverlayViewModel> mDefaultUdfpsTouchOverlayViewModel; + @Mock + private Provider<CameraGestureHelper> mCameraGestureHelper; @Before public void setUp() { @@ -269,7 +274,8 @@ public class UdfpsControllerTest extends SysuiTestCase { mPowerRepository, mock(FalsingCollector.class), mock(ScreenOffAnimationController.class), - mStatusBarStateController + mStatusBarStateController, + mCameraGestureHelper ); mPowerRepository.updateWakefulness( WakefulnessState.AWAKE, diff --git a/packages/SystemUI/tests/src/com/android/systemui/camera/CameraGestureHelperTest.kt b/packages/SystemUI/multivalentTests/src/com/android/systemui/camera/CameraGestureHelperTest.kt index bea0db66555d..a0928ad6dd63 100644 --- a/packages/SystemUI/tests/src/com/android/systemui/camera/CameraGestureHelperTest.kt +++ b/packages/SystemUI/multivalentTests/src/com/android/systemui/camera/CameraGestureHelperTest.kt @@ -18,6 +18,7 @@ package com.android.systemui.camera import android.app.ActivityManager import android.app.IActivityTaskManager +import android.app.admin.DevicePolicyManager import android.content.ComponentName import android.content.ContentResolver import android.content.Intent @@ -29,82 +30,73 @@ import androidx.test.filters.SmallTest import com.android.systemui.ActivityIntentHelper import com.android.systemui.SysuiTestCase import com.android.systemui.plugins.ActivityStarter +import com.android.systemui.statusbar.NotificationLockscreenUserManager import com.android.systemui.statusbar.StatusBarState -import com.android.systemui.statusbar.phone.CentralSurfaces import com.android.systemui.statusbar.phone.StatusBarKeyguardViewManager import com.android.systemui.statusbar.policy.KeyguardStateController import com.android.systemui.user.domain.interactor.SelectedUserInteractor import com.android.systemui.util.mockito.KotlinArgumentCaptor +import com.android.systemui.util.mockito.any import com.android.systemui.util.mockito.eq import com.android.systemui.util.mockito.mock +import com.android.systemui.util.mockito.whenever import com.google.common.truth.Truth.assertThat import com.google.common.util.concurrent.MoreExecutors import org.junit.Before import org.junit.Test import org.junit.runner.RunWith +import org.mockito.ArgumentMatchers.isNull import org.mockito.Mock -import org.mockito.Mockito.any import org.mockito.Mockito.anyInt import org.mockito.Mockito.verify import org.mockito.MockitoAnnotations -import org.mockito.Mockito.`when` as whenever @SmallTest @RunWith(AndroidJUnit4::class) class CameraGestureHelperTest : SysuiTestCase() { - @Mock - lateinit var centralSurfaces: CentralSurfaces - @Mock - lateinit var statusBarKeyguardViewManager: StatusBarKeyguardViewManager - @Mock - lateinit var keyguardStateController: KeyguardStateController - @Mock - lateinit var packageManager: PackageManager - @Mock - lateinit var activityManager: ActivityManager - @Mock - lateinit var activityStarter: ActivityStarter - @Mock - lateinit var activityIntentHelper: ActivityIntentHelper - @Mock - lateinit var activityTaskManager: IActivityTaskManager - @Mock - lateinit var cameraIntents: CameraIntentsWrapper - @Mock - lateinit var contentResolver: ContentResolver - @Mock - lateinit var mSelectedUserInteractor: SelectedUserInteractor + @Mock lateinit var statusBarKeyguardViewManager: StatusBarKeyguardViewManager + @Mock lateinit var keyguardStateController: KeyguardStateController + @Mock lateinit var packageManager: PackageManager + @Mock lateinit var activityManager: ActivityManager + @Mock lateinit var activityStarter: ActivityStarter + @Mock lateinit var activityIntentHelper: ActivityIntentHelper + @Mock lateinit var activityTaskManager: IActivityTaskManager + @Mock lateinit var cameraIntents: CameraIntentsWrapper + @Mock lateinit var contentResolver: ContentResolver + @Mock lateinit var mSelectedUserInteractor: SelectedUserInteractor + @Mock lateinit var devicePolicyManager: DevicePolicyManager + @Mock lateinit var lockscreenUserManager: NotificationLockscreenUserManager private lateinit var underTest: CameraGestureHelper @Before fun setUp() { MockitoAnnotations.initMocks(this) - whenever(cameraIntents.getSecureCameraIntent(anyInt())).thenReturn( - Intent(CameraIntents.DEFAULT_SECURE_CAMERA_INTENT_ACTION) - ) - whenever(cameraIntents.getInsecureCameraIntent(anyInt())).thenReturn( - Intent(CameraIntents.DEFAULT_INSECURE_CAMERA_INTENT_ACTION) - ) + whenever(cameraIntents.getSecureCameraIntent(any())) + .thenReturn(Intent(CameraIntents.DEFAULT_SECURE_CAMERA_INTENT_ACTION)) + whenever(cameraIntents.getInsecureCameraIntent(any())) + .thenReturn(Intent(CameraIntents.DEFAULT_INSECURE_CAMERA_INTENT_ACTION)) prepare() - underTest = CameraGestureHelper( - context = mock(), - centralSurfaces = centralSurfaces, - keyguardStateController = keyguardStateController, - statusBarKeyguardViewManager = statusBarKeyguardViewManager, - packageManager = packageManager, - activityManager = activityManager, - activityStarter = activityStarter, - activityIntentHelper = activityIntentHelper, - activityTaskManager = activityTaskManager, - cameraIntents = cameraIntents, - contentResolver = contentResolver, - uiExecutor = MoreExecutors.directExecutor(), - selectedUserInteractor = mSelectedUserInteractor, - ) + underTest = + CameraGestureHelper( + context = mock(), + keyguardStateController = keyguardStateController, + statusBarKeyguardViewManager = statusBarKeyguardViewManager, + packageManager = packageManager, + activityManager = activityManager, + activityStarter = activityStarter, + activityIntentHelper = activityIntentHelper, + activityTaskManager = activityTaskManager, + cameraIntents = cameraIntents, + contentResolver = contentResolver, + uiExecutor = MoreExecutors.directExecutor(), + selectedUserInteractor = mSelectedUserInteractor, + devicePolicyManager = devicePolicyManager, + lockscreenUserManager = lockscreenUserManager, + ) } /** @@ -116,13 +108,13 @@ class CameraGestureHelperTest : SysuiTestCase() { * @param isCameraAllowedByAdmin Whether the device administrator allows use of the camera app * @param installedCameraAppCount The number of installed camera apps on the device * @param isUsingSecureScreenLockOption Whether the user-controlled setting for Screen Lock is - * set with a "secure" option that requires the user to provide some secret/credentials to be - * able to unlock the device, for example "Face Unlock", "PIN", or "Password". Examples of - * non-secure options are "None" and "Swipe" + * set with a "secure" option that requires the user to provide some secret/credentials to be + * able to unlock the device, for example "Face Unlock", "PIN", or "Password". Examples of + * non-secure options are "None" and "Swipe" * @param isCameraActivityRunningOnTop Whether the camera activity is running at the top of the - * most recent/current task of activities + * most recent/current task of activities * @param isTaskListEmpty Whether there are no active activity tasks at all. Note that this is - * treated as `false` if [isCameraActivityRunningOnTop] is set to `true` + * treated as `false` if [isCameraActivityRunningOnTop] is set to `true` */ private fun prepare( isCameraAllowedByAdmin: Boolean = true, @@ -131,7 +123,13 @@ class CameraGestureHelperTest : SysuiTestCase() { isCameraActivityRunningOnTop: Boolean = false, isTaskListEmpty: Boolean = false, ) { - whenever(centralSurfaces.isCameraAllowedByAdmin).thenReturn(isCameraAllowedByAdmin) + whenever(lockscreenUserManager.getCurrentUserId()).thenReturn(1) + if (isCameraAllowedByAdmin) { + whenever(devicePolicyManager.getCameraDisabled(isNull(), any())).thenReturn(false) + whenever(keyguardStateController.isMethodSecure).thenReturn(false) + } else { + whenever(devicePolicyManager.getCameraDisabled(isNull(), any())).thenReturn(true) + } whenever(activityIntentHelper.wouldLaunchResolverActivity(any(), anyInt())) .thenReturn(installedCameraAppCount > 1) @@ -141,30 +139,26 @@ class CameraGestureHelperTest : SysuiTestCase() { .thenReturn(!isUsingSecureScreenLockOption) if (installedCameraAppCount >= 1) { - val resolveInfo = ResolveInfo().apply { - this.activityInfo = ActivityInfo().apply { - packageName = CAMERA_APP_PACKAGE_NAME + val resolveInfo = + ResolveInfo().apply { + this.activityInfo = + ActivityInfo().apply { packageName = CAMERA_APP_PACKAGE_NAME } } - } - whenever(packageManager.resolveActivityAsUser(any(), anyInt(), anyInt())).thenReturn( - resolveInfo - ) + whenever(packageManager.resolveActivityAsUser(any(), anyInt(), anyInt())) + .thenReturn(resolveInfo) } else { - whenever(packageManager.resolveActivityAsUser(any(), anyInt(), anyInt())).thenReturn( - null - ) + whenever(packageManager.resolveActivityAsUser(any(), anyInt(), anyInt())) + .thenReturn(null) } when { isCameraActivityRunningOnTop -> { - val runningTaskInfo = ActivityManager.RunningTaskInfo().apply { - topActivity = ComponentName(CAMERA_APP_PACKAGE_NAME, "cameraActivity") - } - whenever(activityManager.getRunningTasks(anyInt())).thenReturn( - listOf( - runningTaskInfo - ) - ) + val runningTaskInfo = + ActivityManager.RunningTaskInfo().apply { + topActivity = ComponentName(CAMERA_APP_PACKAGE_NAME, "cameraActivity") + } + whenever(activityManager.getRunningTasks(anyInt())) + .thenReturn(listOf(runningTaskInfo)) } isTaskListEmpty -> { whenever(activityManager.getRunningTasks(anyInt())).thenReturn(emptyList()) @@ -289,28 +283,28 @@ class CameraGestureHelperTest : SysuiTestCase() { ) { val intentCaptor = KotlinArgumentCaptor(Intent::class.java) if (isSecure && !moreThanOneCameraAppInstalled) { - verify(activityTaskManager).startActivityAsUser( - any(), - any(), - any(), - intentCaptor.capture(), - any(), - any(), - any(), - anyInt(), - anyInt(), - any(), - any(), - anyInt() - ) + verify(activityTaskManager) + .startActivityAsUser( + isNull(), + isNull(), + isNull(), + intentCaptor.capture(), + isNull(), + isNull(), + isNull(), + anyInt(), + anyInt(), + isNull(), + any(), + anyInt() + ) } else { verify(activityStarter).startActivity(intentCaptor.capture(), eq(false)) } val intent = intentCaptor.value assertThat(CameraIntents.isSecureCameraIntent(intent)).isEqualTo(isSecure) - assertThat(intent.getIntExtra(CameraIntents.EXTRA_LAUNCH_SOURCE, -1)) - .isEqualTo(source) + assertThat(intent.getIntExtra(CameraIntents.EXTRA_LAUNCH_SOURCE, -1)).isEqualTo(source) } companion object { diff --git a/packages/SystemUI/multivalentTests/src/com/android/systemui/communal/data/repository/CommunalSmartspaceRepositoryImplTest.kt b/packages/SystemUI/multivalentTests/src/com/android/systemui/communal/data/repository/CommunalSmartspaceRepositoryImplTest.kt index c1816ed3e5bf..d2515858dc0b 100644 --- a/packages/SystemUI/multivalentTests/src/com/android/systemui/communal/data/repository/CommunalSmartspaceRepositoryImplTest.kt +++ b/packages/SystemUI/multivalentTests/src/com/android/systemui/communal/data/repository/CommunalSmartspaceRepositoryImplTest.kt @@ -22,6 +22,7 @@ import android.platform.test.annotations.DisableFlags import android.platform.test.annotations.EnableFlags import androidx.test.ext.junit.runners.AndroidJUnit4 import androidx.test.filters.SmallTest +import com.android.systemui.Flags.FLAG_COMMUNAL_TIMER_FLICKER_FIX import com.android.systemui.SysuiTestCase import com.android.systemui.communal.smartspace.CommunalSmartspaceController import com.android.systemui.concurrency.fakeExecutor @@ -97,6 +98,7 @@ class CommunalSmartspaceRepositoryImplTest : SysuiTestCase() { } @EnableFlags(FLAG_REMOTE_VIEWS) + @DisableFlags(FLAG_COMMUNAL_TIMER_FLICKER_FIX) @Test fun communalTimers_onlyShowTimersWithRemoteViews() = testScope.runTest { @@ -138,6 +140,48 @@ class CommunalSmartspaceRepositoryImplTest : SysuiTestCase() { assertThat(communalTimers?.first()?.smartspaceTargetId).isEqualTo("timer-1-started") } + @EnableFlags(FLAG_REMOTE_VIEWS, FLAG_COMMUNAL_TIMER_FLICKER_FIX) + @Test + fun communalTimers_onlyShowTimersWithRemoteViews_timerFlickerFix() = + testScope.runTest { + underTest.startListening() + + val communalTimers by collectLastValue(underTest.timers) + runCurrent() + fakeExecutor.runAllReady() + + with(captureSmartspaceTargetListener()) { + onSmartspaceTargetsUpdated( + listOf( + // Invalid. Not a timer + mock<SmartspaceTarget> { + on { smartspaceTargetId }.doReturn("weather") + on { featureType }.doReturn(SmartspaceTarget.FEATURE_WEATHER) + }, + // Invalid. RemoteViews absent + mock<SmartspaceTarget> { + on { smartspaceTargetId }.doReturn("timer-0-started") + on { featureType }.doReturn(SmartspaceTarget.FEATURE_TIMER) + on { remoteViews }.doReturn(null) + on { creationTimeMillis }.doReturn(1000) + }, + // Valid + mock<SmartspaceTarget> { + on { smartspaceTargetId }.doReturn("timer-1-started") + on { featureType }.doReturn(SmartspaceTarget.FEATURE_TIMER) + on { remoteViews }.doReturn(mock()) + on { creationTimeMillis }.doReturn(2000) + }, + ) + ) + } + runCurrent() + + // Verify that only the valid target is listed + assertThat(communalTimers).hasSize(1) + assertThat(communalTimers?.first()?.smartspaceTargetId).isEqualTo("timer-1") + } + @EnableFlags(FLAG_REMOTE_VIEWS) @Test fun communalTimers_cacheCreationTime() = diff --git a/packages/SystemUI/multivalentTests/src/com/android/systemui/communal/view/viewmodel/CommunalEditModeViewModelTest.kt b/packages/SystemUI/multivalentTests/src/com/android/systemui/communal/view/viewmodel/CommunalEditModeViewModelTest.kt index 61487b0a8c73..57ce9de2d057 100644 --- a/packages/SystemUI/multivalentTests/src/com/android/systemui/communal/view/viewmodel/CommunalEditModeViewModelTest.kt +++ b/packages/SystemUI/multivalentTests/src/com/android/systemui/communal/view/viewmodel/CommunalEditModeViewModelTest.kt @@ -16,6 +16,7 @@ package com.android.systemui.communal.view.viewmodel +import android.appwidget.AppWidgetProviderInfo import android.content.ActivityNotFoundException import android.content.ComponentName import android.content.Intent @@ -24,6 +25,9 @@ import android.content.pm.PackageManager import android.content.pm.ResolveInfo import android.content.pm.UserInfo import android.provider.Settings +import android.view.accessibility.AccessibilityEvent +import android.view.accessibility.AccessibilityManager +import android.view.accessibility.accessibilityManager import android.widget.RemoteViews import androidx.activity.result.ActivityResultLauncher import androidx.test.ext.junit.runners.AndroidJUnit4 @@ -42,7 +46,6 @@ import com.android.systemui.communal.data.repository.fakeCommunalWidgetRepositor import com.android.systemui.communal.domain.interactor.CommunalInteractor import com.android.systemui.communal.domain.interactor.CommunalSceneInteractor import com.android.systemui.communal.domain.interactor.communalInteractor -import com.android.systemui.communal.domain.interactor.communalPrefsInteractor import com.android.systemui.communal.domain.interactor.communalSceneInteractor import com.android.systemui.communal.domain.interactor.communalSettingsInteractor import com.android.systemui.communal.domain.model.CommunalContentModel @@ -61,8 +64,6 @@ import com.android.systemui.media.controls.ui.view.MediaHost import com.android.systemui.settings.fakeUserTracker import com.android.systemui.testKosmos import com.android.systemui.user.data.repository.fakeUserRepository -import com.android.systemui.util.mockito.any -import com.android.systemui.util.mockito.whenever import com.google.common.truth.Truth.assertThat import kotlinx.coroutines.test.advanceTimeBy import kotlinx.coroutines.test.runTest @@ -77,8 +78,12 @@ import org.mockito.Mockito import org.mockito.Mockito.never import org.mockito.Mockito.verify import org.mockito.MockitoAnnotations +import org.mockito.kotlin.any +import org.mockito.kotlin.argumentCaptor import org.mockito.kotlin.eq +import org.mockito.kotlin.mock import org.mockito.kotlin.spy +import org.mockito.kotlin.whenever @SmallTest @RunWith(AndroidJUnit4::class) @@ -98,6 +103,7 @@ class CommunalEditModeViewModelTest : SysuiTestCase() { private lateinit var mediaRepository: FakeCommunalMediaRepository private lateinit var communalSceneInteractor: CommunalSceneInteractor private lateinit var communalInteractor: CommunalInteractor + private lateinit var accessibilityManager: AccessibilityManager private val testableResources = context.orCreateTestableResources @@ -119,6 +125,7 @@ class CommunalEditModeViewModelTest : SysuiTestCase() { selectedUserIndex = 0, ) kosmos.fakeFeatureFlagsClassic.set(Flags.COMMUNAL_SERVICE_ENABLED, true) + accessibilityManager = kosmos.accessibilityManager underTest = CommunalEditModeViewModel( @@ -130,8 +137,10 @@ class CommunalEditModeViewModelTest : SysuiTestCase() { uiEventLogger, logcatLogBuffer("CommunalEditModeViewModelTest"), kosmos.testDispatcher, - kosmos.communalPrefsInteractor, metricsLogger, + context, + accessibilityManager, + packageManager, ) } @@ -356,6 +365,37 @@ class CommunalEditModeViewModelTest : SysuiTestCase() { verify(communalInteractor).setScrollPosition(eq(index), eq(offset)) } + @Test + fun onNewWidgetAdded_accessibilityDisabled_doNothing() { + whenever(accessibilityManager.isEnabled).thenReturn(false) + + val provider = + mock<AppWidgetProviderInfo> { + on { loadLabel(packageManager) }.thenReturn("Test Clock") + } + underTest.onNewWidgetAdded(provider) + + verify(accessibilityManager, never()).sendAccessibilityEvent(any()) + } + + @Test + fun onNewWidgetAdded_accessibilityEnabled_sendAccessibilityAnnouncement() { + whenever(accessibilityManager.isEnabled).thenReturn(true) + + val provider = + mock<AppWidgetProviderInfo> { + on { loadLabel(packageManager) }.thenReturn("Test Clock") + } + underTest.onNewWidgetAdded(provider) + + val captor = argumentCaptor<AccessibilityEvent>() + verify(accessibilityManager).sendAccessibilityEvent(captor.capture()) + + val event = captor.firstValue + assertThat(event.eventType).isEqualTo(AccessibilityEvent.TYPE_ANNOUNCEMENT) + assertThat(event.contentDescription).isEqualTo("Test Clock widget added to lock screen") + } + private companion object { val MAIN_USER_INFO = UserInfo(0, "primary", UserInfo.FLAG_MAIN) const val WIDGET_PICKER_PACKAGE_NAME = "widget_picker_package_name" diff --git a/packages/SystemUI/multivalentTests/src/com/android/systemui/deviceentry/data/repository/DeviceEntryFaceAuthRepositoryTest.kt b/packages/SystemUI/multivalentTests/src/com/android/systemui/deviceentry/data/repository/DeviceEntryFaceAuthRepositoryTest.kt index 2bf50b3daa2f..91259a65eff9 100644 --- a/packages/SystemUI/multivalentTests/src/com/android/systemui/deviceentry/data/repository/DeviceEntryFaceAuthRepositoryTest.kt +++ b/packages/SystemUI/multivalentTests/src/com/android/systemui/deviceentry/data/repository/DeviceEntryFaceAuthRepositoryTest.kt @@ -58,7 +58,6 @@ import com.android.systemui.dump.DumpManager import com.android.systemui.flags.FakeFeatureFlags import com.android.systemui.keyguard.data.repository.BiometricType import com.android.systemui.keyguard.data.repository.fakeBiometricSettingsRepository -import com.android.systemui.keyguard.data.repository.fakeCommandQueue import com.android.systemui.keyguard.data.repository.fakeDeviceEntryFingerprintAuthRepository import com.android.systemui.keyguard.data.repository.fakeKeyguardRepository import com.android.systemui.keyguard.data.repository.fakeKeyguardTransitionRepository @@ -78,7 +77,6 @@ import com.android.systemui.log.table.TableLogBuffer import com.android.systemui.power.domain.interactor.PowerInteractor.Companion.setAsleepForTest import com.android.systemui.power.domain.interactor.PowerInteractor.Companion.setAwakeForTest import com.android.systemui.power.domain.interactor.powerInteractor -import com.android.systemui.statusbar.commandQueue import com.android.systemui.statusbar.phone.KeyguardBypassController import com.android.systemui.testKosmos import com.android.systemui.user.data.model.SelectionStatus @@ -116,7 +114,7 @@ import org.mockito.MockitoAnnotations @SmallTest @RunWith(AndroidJUnit4::class) class DeviceEntryFaceAuthRepositoryTest : SysuiTestCase() { - private val kosmos = testKosmos().apply { this.commandQueue = this.fakeCommandQueue } + private val kosmos = testKosmos() private lateinit var underTest: DeviceEntryFaceAuthRepositoryImpl @Mock private lateinit var faceManager: FaceManager @@ -162,7 +160,6 @@ class DeviceEntryFaceAuthRepositoryTest : SysuiTestCase() { private val displayStateInteractor = kosmos.displayStateInteractor private val bouncerRepository = kosmos.fakeKeyguardBouncerRepository private val displayRepository = kosmos.displayRepository - private val fakeCommandQueue = kosmos.fakeCommandQueue private val keyguardTransitionInteractor = kosmos.keyguardTransitionInteractor private lateinit var featureFlags: FakeFeatureFlags @@ -572,9 +569,7 @@ class DeviceEntryFaceAuthRepositoryTest : SysuiTestCase() { bouncerRepository.setAlternateVisible(false) // Keyguard is occluded when secure camera is active. keyguardRepository.setKeyguardOccluded(true) - fakeCommandQueue.doForEachCallback { - it.onCameraLaunchGestureDetected(CAMERA_LAUNCH_SOURCE_POWER_DOUBLE_TAP) - } + keyguardInteractor.onCameraLaunchDetected(CAMERA_LAUNCH_SOURCE_POWER_DOUBLE_TAP) } } @@ -589,9 +584,7 @@ class DeviceEntryFaceAuthRepositoryTest : SysuiTestCase() { assertThat(canFaceAuthRun()).isTrue() // launch secure camera - fakeCommandQueue.doForEachCallback { - it.onCameraLaunchGestureDetected(CAMERA_LAUNCH_SOURCE_POWER_DOUBLE_TAP) - } + keyguardInteractor.onCameraLaunchDetected(CAMERA_LAUNCH_SOURCE_POWER_DOUBLE_TAP) keyguardRepository.setKeyguardOccluded(true) runCurrent() assertThat(canFaceAuthRun()).isFalse() @@ -870,9 +863,7 @@ class DeviceEntryFaceAuthRepositoryTest : SysuiTestCase() { bouncerRepository.setAlternateVisible(false) // Keyguard is occluded when secure camera is active. keyguardRepository.setKeyguardOccluded(true) - fakeCommandQueue.doForEachCallback { - it.onCameraLaunchGestureDetected(CAMERA_LAUNCH_SOURCE_POWER_DOUBLE_TAP) - } + keyguardInteractor.onCameraLaunchDetected(CAMERA_LAUNCH_SOURCE_POWER_DOUBLE_TAP) } } diff --git a/packages/SystemUI/multivalentTests/src/com/android/systemui/dreams/DreamOverlayServiceTest.kt b/packages/SystemUI/multivalentTests/src/com/android/systemui/dreams/DreamOverlayServiceTest.kt index 4c24ce2ad8c5..5c09777ddde5 100644 --- a/packages/SystemUI/multivalentTests/src/com/android/systemui/dreams/DreamOverlayServiceTest.kt +++ b/packages/SystemUI/multivalentTests/src/com/android/systemui/dreams/DreamOverlayServiceTest.kt @@ -62,12 +62,13 @@ import com.android.systemui.complication.dagger.ComplicationComponent import com.android.systemui.dreams.complication.HideComplicationTouchHandler import com.android.systemui.dreams.dagger.DreamOverlayComponent import com.android.systemui.keyguard.domain.interactor.keyguardInteractor +import com.android.systemui.keyguard.gesture.domain.gestureInteractor import com.android.systemui.kosmos.testScope +import com.android.systemui.navigationbar.gestural.domain.GestureInteractor import com.android.systemui.testKosmos import com.android.systemui.touch.TouchInsetManager import com.android.systemui.util.concurrency.FakeExecutor import com.android.systemui.util.mockito.any -import com.android.systemui.util.mockito.eq import com.android.systemui.util.mockito.whenever import com.android.systemui.util.time.FakeSystemClock import com.google.common.truth.Truth.assertThat @@ -84,9 +85,11 @@ import org.mockito.Mock import org.mockito.Mockito import org.mockito.Mockito.clearInvocations import org.mockito.Mockito.isNull -import org.mockito.Mockito.spy import org.mockito.Mockito.verify import org.mockito.MockitoAnnotations +import org.mockito.kotlin.argumentCaptor +import org.mockito.kotlin.eq +import org.mockito.kotlin.spy @OptIn(ExperimentalCoroutinesApi::class) @SmallTest @@ -166,6 +169,7 @@ class DreamOverlayServiceTest : SysuiTestCase() { private lateinit var bouncerRepository: FakeKeyguardBouncerRepository private lateinit var communalRepository: FakeCommunalSceneRepository private var viewCaptureSpy = spy(ViewCaptureFactory.getInstance(context)) + private lateinit var gestureInteractor: GestureInteractor @Captor var mViewCaptor: ArgumentCaptor<View>? = null private lateinit var mService: DreamOverlayService @@ -177,6 +181,7 @@ class DreamOverlayServiceTest : SysuiTestCase() { lifecycleRegistry = FakeLifecycleRegistry(mLifecycleOwner) bouncerRepository = kosmos.fakeKeyguardBouncerRepository communalRepository = kosmos.fakeCommunalSceneRepository + gestureInteractor = spy(kosmos.gestureInteractor) whenever(mDreamOverlayComponent.getDreamOverlayContainerViewController()) .thenReturn(mDreamOverlayContainerViewController) @@ -231,6 +236,7 @@ class DreamOverlayServiceTest : SysuiTestCase() { HOME_CONTROL_PANEL_DREAM_COMPONENT, mDreamOverlayCallbackController, kosmos.keyguardInteractor, + gestureInteractor, WINDOW_NAME ) } @@ -955,6 +961,47 @@ class DreamOverlayServiceTest : SysuiTestCase() { assertThat(lifecycleRegistry.currentState).isEqualTo(Lifecycle.State.RESUMED) } + @Test + fun testDreamActivityGesturesBlockedOnStart() { + val client = client + + // Inform the overlay service of dream starting. + client.startDream( + mWindowParams, + mDreamOverlayCallback, + DREAM_COMPONENT, + false /*shouldShowComplication*/ + ) + mMainExecutor.runAllReady() + val captor = argumentCaptor<ComponentName>() + verify(gestureInteractor) + .addGestureBlockedActivity(captor.capture(), eq(GestureInteractor.Scope.Global)) + assertThat(captor.firstValue.packageName) + .isEqualTo(ComponentName.unflattenFromString(DREAM_COMPONENT)?.packageName) + } + + @Test + fun testDreamActivityGesturesUnblockedOnEnd() { + val client = client + + // Inform the overlay service of dream starting. + client.startDream( + mWindowParams, + mDreamOverlayCallback, + DREAM_COMPONENT, + false /*shouldShowComplication*/ + ) + mMainExecutor.runAllReady() + + client.endDream() + mMainExecutor.runAllReady() + val captor = argumentCaptor<ComponentName>() + verify(gestureInteractor) + .removeGestureBlockedActivity(captor.capture(), eq(GestureInteractor.Scope.Global)) + assertThat(captor.firstValue.packageName) + .isEqualTo(ComponentName.unflattenFromString(DREAM_COMPONENT)?.packageName) + } + internal class FakeLifecycleRegistry(provider: LifecycleOwner) : LifecycleRegistry(provider) { val mLifecycles: MutableList<State> = ArrayList() diff --git a/packages/SystemUI/multivalentTests/src/com/android/systemui/gesture/data/GestureRepositoryTest.kt b/packages/SystemUI/multivalentTests/src/com/android/systemui/gesture/data/GestureRepositoryTest.kt new file mode 100644 index 000000000000..91d37cf1816a --- /dev/null +++ b/packages/SystemUI/multivalentTests/src/com/android/systemui/gesture/data/GestureRepositoryTest.kt @@ -0,0 +1,53 @@ +/* + * Copyright (C) 2024 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.android.systemui.gesture.data + +import android.content.ComponentName +import androidx.test.ext.junit.runners.AndroidJUnit4 +import androidx.test.filters.SmallTest +import com.android.systemui.SysuiTestCase +import com.android.systemui.coroutines.collectLastValue +import com.android.systemui.navigationbar.gestural.data.respository.GestureRepositoryImpl +import com.google.common.truth.Truth.assertThat +import kotlinx.coroutines.test.StandardTestDispatcher +import kotlinx.coroutines.test.TestScope +import kotlinx.coroutines.test.runTest +import org.junit.Test +import org.junit.runner.RunWith +import org.mockito.kotlin.mock + +@RunWith(AndroidJUnit4::class) +@SmallTest +class GestureRepositoryTest : SysuiTestCase() { + private val testDispatcher = StandardTestDispatcher() + private val testScope = TestScope(testDispatcher) + private val underTest by lazy { GestureRepositoryImpl(testDispatcher) } + + @Test + fun addRemoveComponentToBlock_updatesBlockedComponentSet() = + testScope.runTest { + val component = mock<ComponentName>() + + underTest.addGestureBlockedActivity(component) + val addedBlockedComponents by collectLastValue(underTest.gestureBlockedActivities) + assertThat(addedBlockedComponents).contains(component) + + underTest.removeGestureBlockedActivity(component) + val removedBlockedComponents by collectLastValue(underTest.gestureBlockedActivities) + assertThat(removedBlockedComponents).isEmpty() + } +} diff --git a/packages/SystemUI/multivalentTests/src/com/android/systemui/gesture/domain/GestureInteractorTest.kt b/packages/SystemUI/multivalentTests/src/com/android/systemui/gesture/domain/GestureInteractorTest.kt new file mode 100644 index 000000000000..bc142e62a0aa --- /dev/null +++ b/packages/SystemUI/multivalentTests/src/com/android/systemui/gesture/domain/GestureInteractorTest.kt @@ -0,0 +1,135 @@ +/* + * Copyright (C) 2024 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.android.systemui.gesture.domain + +import android.content.ComponentName +import androidx.test.ext.junit.runners.AndroidJUnit4 +import androidx.test.filters.SmallTest +import com.android.systemui.SysuiTestCase +import com.android.systemui.coroutines.collectLastValue +import com.android.systemui.navigationbar.gestural.data.respository.GestureRepository +import com.android.systemui.navigationbar.gestural.domain.GestureInteractor +import com.google.common.truth.Truth.assertThat +import kotlinx.coroutines.Dispatchers +import kotlinx.coroutines.flow.MutableStateFlow +import kotlinx.coroutines.test.StandardTestDispatcher +import kotlinx.coroutines.test.TestScope +import kotlinx.coroutines.test.resetMain +import kotlinx.coroutines.test.runCurrent +import kotlinx.coroutines.test.runTest +import kotlinx.coroutines.test.setMain +import org.junit.After +import org.junit.Before +import org.junit.Rule +import org.junit.Test +import org.junit.runner.RunWith +import org.mockito.Mock +import org.mockito.junit.MockitoJUnit +import org.mockito.junit.MockitoRule +import org.mockito.kotlin.any +import org.mockito.kotlin.argumentCaptor +import org.mockito.kotlin.mock +import org.mockito.kotlin.never +import org.mockito.kotlin.verify +import org.mockito.kotlin.whenever + +@RunWith(AndroidJUnit4::class) +@SmallTest +class GestureInteractorTest : SysuiTestCase() { + @Rule @JvmField val mockitoRule: MockitoRule = MockitoJUnit.rule() + + val dispatcher = StandardTestDispatcher() + val testScope = TestScope(dispatcher) + + @Mock private lateinit var gestureRepository: GestureRepository + + private val underTest by lazy { + GestureInteractor(gestureRepository, testScope.backgroundScope) + } + + @Before + fun setup() { + Dispatchers.setMain(dispatcher) + whenever(gestureRepository.gestureBlockedActivities).thenReturn(MutableStateFlow(setOf())) + } + + @After + fun tearDown() { + Dispatchers.resetMain() + } + + @Test + fun addBlockedActivity_testCombination() = + testScope.runTest { + val globalComponent = mock<ComponentName>() + whenever(gestureRepository.gestureBlockedActivities) + .thenReturn(MutableStateFlow(setOf(globalComponent))) + val localComponent = mock<ComponentName>() + underTest.addGestureBlockedActivity(localComponent, GestureInteractor.Scope.Local) + val lastSeen by collectLastValue(underTest.gestureBlockedActivities) + testScope.runCurrent() + verify(gestureRepository, never()).addGestureBlockedActivity(any()) + assertThat(lastSeen).hasSize(2) + assertThat(lastSeen).containsExactly(globalComponent, localComponent) + } + + @Test + fun addBlockedActivityLocally_onlyAffectsLocalInteractor() = + testScope.runTest { + val component = mock<ComponentName>() + underTest.addGestureBlockedActivity(component, GestureInteractor.Scope.Local) + val lastSeen by collectLastValue(underTest.gestureBlockedActivities) + testScope.runCurrent() + verify(gestureRepository, never()).addGestureBlockedActivity(any()) + assertThat(lastSeen).contains(component) + } + + @Test + fun removeBlockedActivityLocally_onlyAffectsLocalInteractor() = + testScope.runTest { + val component = mock<ComponentName>() + underTest.addGestureBlockedActivity(component, GestureInteractor.Scope.Local) + val lastSeen by collectLastValue(underTest.gestureBlockedActivities) + testScope.runCurrent() + underTest.removeGestureBlockedActivity(component, GestureInteractor.Scope.Local) + testScope.runCurrent() + verify(gestureRepository, never()).removeGestureBlockedActivity(any()) + assertThat(lastSeen).isEmpty() + } + + @Test + fun addBlockedActivity_invokesRepository() = + testScope.runTest { + val component = mock<ComponentName>() + underTest.addGestureBlockedActivity(component, GestureInteractor.Scope.Global) + runCurrent() + val captor = argumentCaptor<ComponentName>() + verify(gestureRepository).addGestureBlockedActivity(captor.capture()) + assertThat(captor.firstValue).isEqualTo(component) + } + + @Test + fun removeBlockedActivity_invokesRepository() = + testScope.runTest { + val component = mock<ComponentName>() + underTest.removeGestureBlockedActivity(component, GestureInteractor.Scope.Global) + runCurrent() + val captor = argumentCaptor<ComponentName>() + verify(gestureRepository).removeGestureBlockedActivity(captor.capture()) + assertThat(captor.firstValue).isEqualTo(component) + } +} diff --git a/packages/SystemUI/multivalentTests/src/com/android/systemui/haptics/qs/QSLongPressEffectTest.kt b/packages/SystemUI/multivalentTests/src/com/android/systemui/haptics/qs/QSLongPressEffectTest.kt index 18839e6acb96..273e3cbe76ea 100644 --- a/packages/SystemUI/multivalentTests/src/com/android/systemui/haptics/qs/QSLongPressEffectTest.kt +++ b/packages/SystemUI/multivalentTests/src/com/android/systemui/haptics/qs/QSLongPressEffectTest.kt @@ -23,9 +23,9 @@ import androidx.test.ext.junit.runners.AndroidJUnit4 import androidx.test.filters.SmallTest import com.android.systemui.SysuiTestCase import com.android.systemui.animation.ActivityTransitionAnimator -import com.android.systemui.classifier.falsingManager import com.android.systemui.haptics.vibratorHelper import com.android.systemui.kosmos.testScope +import com.android.systemui.log.core.FakeLogBuffer import com.android.systemui.qs.qsTileFactory import com.android.systemui.statusbar.policy.keyguardStateController import com.android.systemui.testKosmos @@ -73,7 +73,7 @@ class QSLongPressEffectTest : SysuiTestCase() { QSLongPressEffect( vibratorHelper, kosmos.keyguardStateController, - kosmos.falsingManager, + FakeLogBuffer.Factory.create(), ) longPressEffect.callback = callback longPressEffect.qsTile = qsTile @@ -304,13 +304,12 @@ class QSLongPressEffectTest : SysuiTestCase() { } @Test - fun getStateForClick_withFalseTapWhenLocked_returnsIdle() { + fun getStateForClick_whenKeyguardsIsShowing_returnsIdle() { // GIVEN an active tile qsTile.state?.state = Tile.STATE_ACTIVE - // GIVEN that the device is locked and a false tap is detected - whenever(kosmos.keyguardStateController.isUnlocked).thenReturn(false) - kosmos.falsingManager.setFalseTap(true) + // GIVEN that the keyguard is showing + whenever(kosmos.keyguardStateController.isShowing).thenReturn(true) // WHEN determining the state of a click action val clickState = longPressEffect.getStateForClick() @@ -324,9 +323,8 @@ class QSLongPressEffectTest : SysuiTestCase() { // GIVEN an active tile qsTile.state?.state = Tile.STATE_ACTIVE - // GIVEN that the device is locked and a false tap is not detected - whenever(kosmos.keyguardStateController.isUnlocked).thenReturn(false) - kosmos.falsingManager.setFalseTap(false) + // GIVEN that the keyguard is not showing + whenever(kosmos.keyguardStateController.isShowing).thenReturn(false) // WHEN determining the state of a click action val clickState = longPressEffect.getStateForClick() @@ -340,9 +338,8 @@ class QSLongPressEffectTest : SysuiTestCase() { // GIVEN that the tile is null longPressEffect.qsTile = null - // GIVEN that the device is locked and a false tap is not detected - whenever(kosmos.keyguardStateController.isUnlocked).thenReturn(false) - kosmos.falsingManager.setFalseTap(false) + // GIVEN that the keyguard is not showing + whenever(kosmos.keyguardStateController.isShowing).thenReturn(false) // WHEN determining the state of a click action val clickState = longPressEffect.getStateForClick() diff --git a/packages/SystemUI/multivalentTests/src/com/android/systemui/keyguard/domain/interactor/FromAlternateBouncerTransitionInteractorTest.kt b/packages/SystemUI/multivalentTests/src/com/android/systemui/keyguard/domain/interactor/FromAlternateBouncerTransitionInteractorTest.kt index 5115f5af94f0..3b8ffcd91c48 100644 --- a/packages/SystemUI/multivalentTests/src/com/android/systemui/keyguard/domain/interactor/FromAlternateBouncerTransitionInteractorTest.kt +++ b/packages/SystemUI/multivalentTests/src/com/android/systemui/keyguard/domain/interactor/FromAlternateBouncerTransitionInteractorTest.kt @@ -173,6 +173,7 @@ class FromAlternateBouncerTransitionInteractorTest : SysuiTestCase() { } @Test + @DisableFlags(Flags.FLAG_KEYGUARD_WM_STATE_REFACTOR) fun transitionToGone_whenOpeningGlanceableHubEditMode() = testScope.runTest { kosmos.fakeKeyguardBouncerRepository.setAlternateVisible(true) diff --git a/packages/SystemUI/multivalentTests/src/com/android/systemui/keyguard/domain/interactor/KeyguardInteractorTest.kt b/packages/SystemUI/multivalentTests/src/com/android/systemui/keyguard/domain/interactor/KeyguardInteractorTest.kt index 7906a8244c5d..fc827a1478c7 100644 --- a/packages/SystemUI/multivalentTests/src/com/android/systemui/keyguard/domain/interactor/KeyguardInteractorTest.kt +++ b/packages/SystemUI/multivalentTests/src/com/android/systemui/keyguard/domain/interactor/KeyguardInteractorTest.kt @@ -32,7 +32,7 @@ import com.android.systemui.flags.EnableSceneContainer import com.android.systemui.keyguard.data.repository.fakeCommandQueue import com.android.systemui.keyguard.data.repository.fakeKeyguardRepository import com.android.systemui.keyguard.data.repository.fakeKeyguardTransitionRepository -import com.android.systemui.keyguard.shared.model.CameraLaunchSourceModel +import com.android.systemui.keyguard.shared.model.CameraLaunchType import com.android.systemui.keyguard.shared.model.KeyguardState import com.android.systemui.keyguard.shared.model.StatusBarState import com.android.systemui.keyguard.shared.model.TransitionState @@ -47,7 +47,6 @@ import com.google.common.truth.Truth.assertThat import kotlinx.coroutines.ExperimentalCoroutinesApi import kotlinx.coroutines.flow.MutableStateFlow import kotlinx.coroutines.flow.flowOf -import kotlinx.coroutines.flow.onCompletion import kotlinx.coroutines.test.runCurrent import kotlinx.coroutines.test.runTest import org.junit.Before @@ -87,31 +86,17 @@ class KeyguardInteractorTest : SysuiTestCase() { val cameraLaunchSource = collectLastValue(flow) runCurrent() - commandQueue.doForEachCallback { - it.onCameraLaunchGestureDetected(StatusBarManager.CAMERA_LAUNCH_SOURCE_WIGGLE) - } - assertThat(cameraLaunchSource()).isEqualTo(CameraLaunchSourceModel.WIGGLE) + underTest.onCameraLaunchDetected(StatusBarManager.CAMERA_LAUNCH_SOURCE_POWER_DOUBLE_TAP) + assertThat(cameraLaunchSource()!!.type).isEqualTo(CameraLaunchType.POWER_DOUBLE_TAP) - commandQueue.doForEachCallback { - it.onCameraLaunchGestureDetected( - StatusBarManager.CAMERA_LAUNCH_SOURCE_POWER_DOUBLE_TAP - ) - } - assertThat(cameraLaunchSource()).isEqualTo(CameraLaunchSourceModel.POWER_DOUBLE_TAP) - - commandQueue.doForEachCallback { - it.onCameraLaunchGestureDetected(StatusBarManager.CAMERA_LAUNCH_SOURCE_LIFT_TRIGGER) - } - assertThat(cameraLaunchSource()).isEqualTo(CameraLaunchSourceModel.LIFT_TRIGGER) + underTest.onCameraLaunchDetected(StatusBarManager.CAMERA_LAUNCH_SOURCE_WIGGLE) + assertThat(cameraLaunchSource()!!.type).isEqualTo(CameraLaunchType.WIGGLE) - commandQueue.doForEachCallback { - it.onCameraLaunchGestureDetected( - StatusBarManager.CAMERA_LAUNCH_SOURCE_QUICK_AFFORDANCE - ) - } - assertThat(cameraLaunchSource()).isEqualTo(CameraLaunchSourceModel.QUICK_AFFORDANCE) + underTest.onCameraLaunchDetected(StatusBarManager.CAMERA_LAUNCH_SOURCE_LIFT_TRIGGER) + assertThat(cameraLaunchSource()!!.type).isEqualTo(CameraLaunchType.LIFT_TRIGGER) - flow.onCompletion { assertThat(commandQueue.callbackCount()).isEqualTo(0) } + underTest.onCameraLaunchDetected(StatusBarManager.CAMERA_LAUNCH_SOURCE_QUICK_AFFORDANCE) + assertThat(cameraLaunchSource()!!.type).isEqualTo(CameraLaunchType.QUICK_AFFORDANCE) } @Test @@ -121,11 +106,7 @@ class KeyguardInteractorTest : SysuiTestCase() { val secureCameraActive = collectLastValue(underTest.isSecureCameraActive) runCurrent() - commandQueue.doForEachCallback { - it.onCameraLaunchGestureDetected( - StatusBarManager.CAMERA_LAUNCH_SOURCE_POWER_DOUBLE_TAP - ) - } + underTest.onCameraLaunchDetected(StatusBarManager.CAMERA_LAUNCH_SOURCE_POWER_DOUBLE_TAP) assertThat(secureCameraActive()).isTrue() @@ -146,11 +127,7 @@ class KeyguardInteractorTest : SysuiTestCase() { val secureCameraActive = collectLastValue(underTest.isSecureCameraActive) runCurrent() - commandQueue.doForEachCallback { - it.onCameraLaunchGestureDetected( - StatusBarManager.CAMERA_LAUNCH_SOURCE_POWER_DOUBLE_TAP - ) - } + underTest.onCameraLaunchDetected(StatusBarManager.CAMERA_LAUNCH_SOURCE_POWER_DOUBLE_TAP) assertThat(secureCameraActive()).isTrue() // Keyguard is showing and not occluded diff --git a/packages/SystemUI/multivalentTests/src/com/android/systemui/keyguard/domain/interactor/KeyguardTransitionScenariosTest.kt b/packages/SystemUI/multivalentTests/src/com/android/systemui/keyguard/domain/interactor/KeyguardTransitionScenariosTest.kt index d9708a4f5506..9762fd8e2158 100644 --- a/packages/SystemUI/multivalentTests/src/com/android/systemui/keyguard/domain/interactor/KeyguardTransitionScenariosTest.kt +++ b/packages/SystemUI/multivalentTests/src/com/android/systemui/keyguard/domain/interactor/KeyguardTransitionScenariosTest.kt @@ -16,7 +16,7 @@ package com.android.systemui.keyguard.domain.interactor -import android.app.StatusBarManager +import android.app.StatusBarManager.CAMERA_LAUNCH_SOURCE_POWER_DOUBLE_TAP import android.platform.test.annotations.DisableFlags import android.platform.test.annotations.EnableFlags import android.platform.test.flag.junit.FlagsParameterization @@ -42,7 +42,6 @@ import com.android.systemui.flags.Flags.COMMUNAL_SERVICE_ENABLED import com.android.systemui.flags.andSceneContainer import com.android.systemui.flags.fakeFeatureFlagsClassic import com.android.systemui.keyguard.data.repository.FakeKeyguardTransitionRepository -import com.android.systemui.keyguard.data.repository.fakeCommandQueue import com.android.systemui.keyguard.data.repository.fakeKeyguardRepository import com.android.systemui.keyguard.data.repository.fakeKeyguardTransitionRepository import com.android.systemui.keyguard.shared.model.BiometricUnlockMode @@ -59,7 +58,6 @@ import com.android.systemui.power.domain.interactor.PowerInteractor.Companion.se import com.android.systemui.power.domain.interactor.powerInteractor import com.android.systemui.scene.shared.flag.SceneContainerFlag import com.android.systemui.shade.shadeTestUtil -import com.android.systemui.statusbar.commandQueue import com.android.systemui.testKosmos import com.android.systemui.util.mockito.whenever import kotlinx.coroutines.ExperimentalCoroutinesApi @@ -93,13 +91,12 @@ class KeyguardTransitionScenariosTest(flags: FlagsParameterization?) : SysuiTest private val kosmos = testKosmos().apply { fakeKeyguardTransitionRepository = spy(FakeKeyguardTransitionRepository()) - this.commandQueue = fakeCommandQueue } private val testScope = kosmos.testScope private val keyguardRepository by lazy { kosmos.fakeKeyguardRepository } + private val keyguardInteractor by lazy { kosmos.keyguardInteractor } private val bouncerRepository by lazy { kosmos.fakeKeyguardBouncerRepository } - private var commandQueue = kosmos.fakeCommandQueue private val shadeTestUtil by lazy { kosmos.shadeTestUtil } private val transitionRepository by lazy { kosmos.fakeKeyguardTransitionRepository } private lateinit var featureFlags: FakeFeatureFlags @@ -1724,11 +1721,7 @@ class KeyguardTransitionScenariosTest(flags: FlagsParameterization?) : SysuiTest reset(transitionRepository) // ...AND WHEN the camera gesture is detected quickly afterwards - commandQueue.doForEachCallback { - it.onCameraLaunchGestureDetected( - StatusBarManager.CAMERA_LAUNCH_SOURCE_POWER_DOUBLE_TAP - ) - } + keyguardInteractor.onCameraLaunchDetected(CAMERA_LAUNCH_SOURCE_POWER_DOUBLE_TAP) runCurrent() // THEN a transition from DOZING => OCCLUDED should occur diff --git a/packages/SystemUI/multivalentTests/src/com/android/systemui/keyguard/ui/viewmodel/AlternateBouncerToLockscreenTransitionViewModelTest.kt b/packages/SystemUI/multivalentTests/src/com/android/systemui/keyguard/ui/viewmodel/AlternateBouncerToLockscreenTransitionViewModelTest.kt new file mode 100644 index 000000000000..f74b74a9f618 --- /dev/null +++ b/packages/SystemUI/multivalentTests/src/com/android/systemui/keyguard/ui/viewmodel/AlternateBouncerToLockscreenTransitionViewModelTest.kt @@ -0,0 +1,125 @@ +/* + * Copyright (C) 2024 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.android.systemui.keyguard.ui.viewmodel + +import androidx.test.ext.junit.runners.AndroidJUnit4 +import androidx.test.filters.SmallTest +import com.android.systemui.SysuiTestCase +import com.android.systemui.biometrics.data.repository.fingerprintPropertyRepository +import com.android.systemui.coroutines.collectLastValue +import com.android.systemui.coroutines.collectValues +import com.android.systemui.keyguard.data.repository.fakeKeyguardTransitionRepository +import com.android.systemui.keyguard.shared.model.KeyguardState +import com.android.systemui.keyguard.shared.model.TransitionState +import com.android.systemui.keyguard.shared.model.TransitionState.RUNNING +import com.android.systemui.keyguard.shared.model.TransitionStep +import com.android.systemui.kosmos.testScope +import com.android.systemui.testKosmos +import com.google.common.truth.Truth.assertThat +import kotlinx.coroutines.ExperimentalCoroutinesApi +import kotlinx.coroutines.test.runCurrent +import kotlinx.coroutines.test.runTest +import org.junit.Test +import org.junit.runner.RunWith + +@ExperimentalCoroutinesApi +@SmallTest +@RunWith(AndroidJUnit4::class) +class AlternateBouncerToLockscreenTransitionViewModelTest : SysuiTestCase() { + val kosmos = testKosmos() + val testScope = kosmos.testScope + + val keyguardTransitionRepository = kosmos.fakeKeyguardTransitionRepository + val fingerprintPropertyRepository = kosmos.fingerprintPropertyRepository + + val underTest = kosmos.alternateBouncerToLockscreenTransitionViewModel + + @Test + fun lockscreenAlpha_zeroInitialAlpha() = + testScope.runTest { + // ViewState starts at 0 alpha. + val viewState = ViewStateAccessor(alpha = { 0f }) + val alpha by collectValues(underTest.lockscreenAlpha(viewState)) + + keyguardTransitionRepository.sendTransitionSteps( + from = KeyguardState.ALTERNATE_BOUNCER, + to = KeyguardState.LOCKSCREEN, + testScope + ) + + assertThat(alpha[0]).isEqualTo(0f) + // alpha duration is 250ms of the 300ms total, so 0.5f of the total is 0.6 + assertThat(alpha[1]).isEqualTo(0.6f) + assertThat(alpha[2]).isEqualTo(1f) + } + + @Test + fun deviceEntryParentViewAlpha() = + testScope.runTest { + val deviceEntryParentViewAlpha by collectLastValue(underTest.deviceEntryParentViewAlpha) + + // immediately 1f + keyguardTransitionRepository.sendTransitionStep(step(0f, TransitionState.STARTED)) + assertThat(deviceEntryParentViewAlpha).isEqualTo(1f) + + keyguardTransitionRepository.sendTransitionStep(step(0.4f)) + assertThat(deviceEntryParentViewAlpha).isEqualTo(1f) + + keyguardTransitionRepository.sendTransitionStep(step(.85f)) + assertThat(deviceEntryParentViewAlpha).isEqualTo(1f) + + keyguardTransitionRepository.sendTransitionStep(step(1f)) + assertThat(deviceEntryParentViewAlpha).isEqualTo(1f) + } + + @Test + fun deviceEntryBackgroundViewAlpha_udfpsEnrolled_show() = + testScope.runTest { + fingerprintPropertyRepository.supportsUdfps() + val bgViewAlpha by collectLastValue(underTest.deviceEntryBackgroundViewAlpha) + runCurrent() + + // immediately 1f + keyguardTransitionRepository.sendTransitionStep(step(0f, TransitionState.STARTED)) + assertThat(bgViewAlpha).isEqualTo(1f) + + keyguardTransitionRepository.sendTransitionStep(step(0.1f)) + assertThat(bgViewAlpha).isEqualTo(1f) + + keyguardTransitionRepository.sendTransitionStep(step(.3f)) + assertThat(bgViewAlpha).isEqualTo(1f) + + keyguardTransitionRepository.sendTransitionStep(step(.5f)) + assertThat(bgViewAlpha).isEqualTo(1f) + + keyguardTransitionRepository.sendTransitionStep(step(1f, TransitionState.FINISHED)) + assertThat(bgViewAlpha).isEqualTo(1f) + } + + private fun step( + value: Float, + state: TransitionState = TransitionState.RUNNING + ): TransitionStep { + return TransitionStep( + from = KeyguardState.ALTERNATE_BOUNCER, + to = KeyguardState.LOCKSCREEN, + value = value, + transitionState = state, + ownerName = "AlternateBouncerToLockscreenTransitionViewModelTest" + ) + } +} diff --git a/packages/SystemUI/tests/src/com/android/systemui/power/domain/interactor/PowerInteractorTest.kt b/packages/SystemUI/multivalentTests/src/com/android/systemui/power/domain/interactor/PowerInteractorTest.kt index 12c9eb900ee1..53dec696004d 100644 --- a/packages/SystemUI/tests/src/com/android/systemui/power/domain/interactor/PowerInteractorTest.kt +++ b/packages/SystemUI/multivalentTests/src/com/android/systemui/power/domain/interactor/PowerInteractorTest.kt @@ -21,22 +21,23 @@ import android.os.PowerManager 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.classifier.FalsingCollector +import com.android.systemui.coroutines.collectLastValue import com.android.systemui.keyguard.data.repository.FakeKeyguardRepository -import com.android.systemui.power.shared.model.WakeSleepReason -import com.android.systemui.power.shared.model.WakefulnessState +import com.android.systemui.kosmos.testScope import com.android.systemui.plugins.statusbar.StatusBarStateController import com.android.systemui.power.data.repository.FakePowerRepository +import com.android.systemui.power.shared.model.WakeSleepReason +import com.android.systemui.power.shared.model.WakefulnessState import com.android.systemui.statusbar.phone.ScreenOffAnimationController +import com.android.systemui.testKosmos +import com.android.systemui.util.mockito.any import com.android.systemui.util.mockito.whenever import com.google.common.truth.Truth.assertThat import junit.framework.Assert.assertFalse import junit.framework.Assert.assertTrue -import kotlin.test.assertEquals -import kotlinx.coroutines.Dispatchers -import kotlinx.coroutines.flow.launchIn -import kotlinx.coroutines.flow.onEach -import kotlinx.coroutines.runBlocking +import kotlinx.coroutines.test.runTest import org.junit.Before import org.junit.Test import org.junit.runner.RunWith @@ -47,6 +48,9 @@ import org.mockito.MockitoAnnotations @SmallTest @RunWith(AndroidJUnit4::class) class PowerInteractorTest : SysuiTestCase() { + private val kosmos = testKosmos() + private val testScope = kosmos.testScope + private val cameraGestureHelper = kosmos.cameraGestureHelper private lateinit var underTest: PowerInteractor private lateinit var repository: FakePowerRepository @@ -66,33 +70,30 @@ class PowerInteractorTest : SysuiTestCase() { falsingCollector, screenOffAnimationController, statusBarStateController, + { cameraGestureHelper }, ) + + whenever(cameraGestureHelper.canCameraGestureBeLaunched(any())).thenReturn(true) } @Test fun isInteractive_screenTurnsOff() = - runBlocking(IMMEDIATE) { + testScope.runTest { repository.setInteractive(true) - var value: Boolean? = null - val job = underTest.isInteractive.onEach { value = it }.launchIn(this) + val isInteractive by collectLastValue(underTest.isInteractive) repository.setInteractive(false) - - assertThat(value).isFalse() - job.cancel() + assertThat(isInteractive).isFalse() } @Test fun isInteractive_becomesInteractive() = - runBlocking(IMMEDIATE) { + testScope.runTest { repository.setInteractive(false) - var value: Boolean? = null - val job = underTest.isInteractive.onEach { value = it }.launchIn(this) + val isInteractive by collectLastValue(underTest.isInteractive) repository.setInteractive(true) - - assertThat(value).isTrue() - job.cancel() + assertThat(isInteractive).isTrue() } @Test @@ -203,6 +204,23 @@ class PowerInteractorTest : SysuiTestCase() { } @Test + fun onCameraLaunchGestureDetected_isNotTrueWhenCannotLaunch() { + whenever(cameraGestureHelper.canCameraGestureBeLaunched(any())).thenReturn(false) + underTest.onStartedWakingUp( + PowerManager.WAKE_REASON_POWER_BUTTON, + /*powerButtonLaunchGestureTriggeredDuringSleep= */ false + ) + underTest.onFinishedWakingUp() + underTest.onCameraLaunchGestureDetected() + + assertThat(repository.wakefulness.value.internalWakefulnessState) + .isEqualTo(WakefulnessState.AWAKE) + assertThat(repository.wakefulness.value.lastWakeReason) + .isEqualTo(WakeSleepReason.POWER_BUTTON) + assertFalse(repository.wakefulness.value.powerButtonLaunchGestureTriggered) + } + + @Test fun onCameraLaunchGestureDetected_maintainsAllOtherState() { underTest.onStartedWakingUp( PowerManager.WAKE_REASON_POWER_BUTTON, @@ -211,8 +229,10 @@ class PowerInteractorTest : SysuiTestCase() { underTest.onFinishedWakingUp() underTest.onCameraLaunchGestureDetected() - assertEquals(WakefulnessState.AWAKE, repository.wakefulness.value.internalWakefulnessState) - assertEquals(WakeSleepReason.POWER_BUTTON, repository.wakefulness.value.lastWakeReason) + assertThat(repository.wakefulness.value.internalWakefulnessState) + .isEqualTo(WakefulnessState.AWAKE) + assertThat(repository.wakefulness.value.lastWakeReason) + .isEqualTo(WakeSleepReason.POWER_BUTTON) assertTrue(repository.wakefulness.value.powerButtonLaunchGestureTriggered) } @@ -221,21 +241,23 @@ class PowerInteractorTest : SysuiTestCase() { underTest.onCameraLaunchGestureDetected() // Ensure that the 'false' here does not clear the direct launch detection call earlier. // This state should only be reset onStartedGoingToSleep. - underTest.onFinishedGoingToSleep(/*powerButtonLaunchGestureTriggeredDuringSleep= */ false) + underTest.onFinishedGoingToSleep(/* powerButtonLaunchGestureTriggeredDuringSleep= */ false) underTest.onStartedWakingUp( PowerManager.WAKE_REASON_POWER_BUTTON, /*powerButtonLaunchGestureTriggeredDuringSleep= */ false ) underTest.onFinishedWakingUp() - assertEquals(WakefulnessState.AWAKE, repository.wakefulness.value.internalWakefulnessState) - assertEquals(WakeSleepReason.POWER_BUTTON, repository.wakefulness.value.lastWakeReason) + assertThat(repository.wakefulness.value.internalWakefulnessState) + .isEqualTo(WakefulnessState.AWAKE) + assertThat(repository.wakefulness.value.lastWakeReason) + .isEqualTo(WakeSleepReason.POWER_BUTTON) assertTrue(repository.wakefulness.value.powerButtonLaunchGestureTriggered) } @Test fun cameraLaunchDetectedOnGoingToSleep_stillTrue_ifGestureNotDetectedOnWakingUp() { - underTest.onFinishedGoingToSleep(/*powerButtonLaunchGestureTriggeredDuringSleep= */ true) + underTest.onFinishedGoingToSleep(/* powerButtonLaunchGestureTriggeredDuringSleep= */ true) // Ensure that the 'false' here does not clear the direct launch detection call earlier. // This state should only be reset onStartedGoingToSleep. underTest.onStartedWakingUp( @@ -244,12 +266,10 @@ class PowerInteractorTest : SysuiTestCase() { ) underTest.onFinishedWakingUp() - assertEquals(WakefulnessState.AWAKE, repository.wakefulness.value.internalWakefulnessState) - assertEquals(WakeSleepReason.POWER_BUTTON, repository.wakefulness.value.lastWakeReason) + assertThat(repository.wakefulness.value.internalWakefulnessState) + .isEqualTo(WakefulnessState.AWAKE) + assertThat(repository.wakefulness.value.lastWakeReason) + .isEqualTo(WakeSleepReason.POWER_BUTTON) assertTrue(repository.wakefulness.value.powerButtonLaunchGestureTriggered) } - - companion object { - private val IMMEDIATE = Dispatchers.Main.immediate - } } diff --git a/packages/SystemUI/multivalentTests/src/com/android/systemui/qs/pipeline/domain/interactor/CurrentTilesInteractorImplTest.kt b/packages/SystemUI/multivalentTests/src/com/android/systemui/qs/pipeline/domain/interactor/CurrentTilesInteractorImplTest.kt index 6ad4b317b94c..314631823e96 100644 --- a/packages/SystemUI/multivalentTests/src/com/android/systemui/qs/pipeline/domain/interactor/CurrentTilesInteractorImplTest.kt +++ b/packages/SystemUI/multivalentTests/src/com/android/systemui/qs/pipeline/domain/interactor/CurrentTilesInteractorImplTest.kt @@ -675,6 +675,24 @@ class CurrentTilesInteractorImplTest : SysuiTestCase() { assertThat(tiles!!.size).isEqualTo(3) } + @Test + fun changeInPackagesTiles_doesntTriggerUserChange_logged() = + testScope.runTest(USER_INFO_0) { + val specs = + listOf( + TileSpec.create("a"), + ) + tileSpecRepository.setTiles(USER_INFO_0.id, specs) + runCurrent() + // Settled on the same list of tiles. + assertThat(underTest.currentTilesSpecs).isEqualTo(specs) + + installedTilesPackageRepository.setInstalledPackagesForUser(USER_INFO_0.id, emptySet()) + runCurrent() + + verify(logger, never()).logTileUserChanged(TileSpec.create("a"), 0) + } + private fun QSTile.State.fillIn(state: Int, label: CharSequence, secondaryLabel: CharSequence) { this.state = state this.label = label diff --git a/packages/SystemUI/multivalentTests/src/com/android/systemui/qs/tiles/impl/modes/domain/interactor/ModesTileDataInteractorTest.kt b/packages/SystemUI/multivalentTests/src/com/android/systemui/qs/tiles/impl/modes/domain/interactor/ModesTileDataInteractorTest.kt index 09dca25d693e..69b8ee10107e 100644 --- a/packages/SystemUI/multivalentTests/src/com/android/systemui/qs/tiles/impl/modes/domain/interactor/ModesTileDataInteractorTest.kt +++ b/packages/SystemUI/multivalentTests/src/com/android/systemui/qs/tiles/impl/modes/domain/interactor/ModesTileDataInteractorTest.kt @@ -22,11 +22,14 @@ import android.platform.test.annotations.DisableFlags import android.platform.test.annotations.EnableFlags import androidx.test.ext.junit.runners.AndroidJUnit4 import androidx.test.filters.SmallTest -import com.android.settingslib.notification.data.repository.FakeZenModeRepository import com.android.systemui.SysuiTestCase import com.android.systemui.coroutines.collectValues +import com.android.systemui.kosmos.testDispatcher +import com.android.systemui.kosmos.testScope import com.android.systemui.qs.tiles.base.interactor.DataUpdateTrigger import com.android.systemui.qs.tiles.impl.modes.domain.model.ModesTileModel +import com.android.systemui.statusbar.policy.data.repository.fakeZenModeRepository +import com.android.systemui.testKosmos import com.google.common.truth.Truth.assertThat import kotlinx.coroutines.ExperimentalCoroutinesApi import kotlinx.coroutines.flow.flowOf @@ -40,51 +43,72 @@ import org.junit.runner.RunWith @SmallTest @RunWith(AndroidJUnit4::class) class ModesTileDataInteractorTest : SysuiTestCase() { - private val zenModeRepository = FakeZenModeRepository() + private val kosmos = testKosmos() + private val testScope = kosmos.testScope + private val dispatcher = kosmos.testDispatcher + private val zenModeRepository = kosmos.fakeZenModeRepository - private val underTest = ModesTileDataInteractor(zenModeRepository) + private val underTest = ModesTileDataInteractor(zenModeRepository, dispatcher) @EnableFlags(Flags.FLAG_MODES_UI) @Test - fun availableWhenFlagIsOn() = runTest { - val availability = underTest.availability(TEST_USER).toCollection(mutableListOf()) + fun availableWhenFlagIsOn() = + testScope.runTest { + val availability = underTest.availability(TEST_USER).toCollection(mutableListOf()) - assertThat(availability).containsExactly(true) - } + assertThat(availability).containsExactly(true) + } @DisableFlags(Flags.FLAG_MODES_UI) @Test - fun unavailableWhenFlagIsOff() = runTest { - val availability = underTest.availability(TEST_USER).toCollection(mutableListOf()) + fun unavailableWhenFlagIsOff() = + testScope.runTest { + val availability = underTest.availability(TEST_USER).toCollection(mutableListOf()) - assertThat(availability).containsExactly(false) - } + assertThat(availability).containsExactly(false) + } @EnableFlags(Flags.FLAG_MODES_UI) @Test - fun isActivatedWhenModesChange() = runTest { - val dataList: List<ModesTileModel> by - collectValues(underTest.tileData(TEST_USER, flowOf(DataUpdateTrigger.InitialRequest))) - runCurrent() - assertThat(dataList.map { it.isActivated }).containsExactly(false).inOrder() + fun isActivatedWhenModesChange() = + testScope.runTest { + val dataList: List<ModesTileModel> by + collectValues( + underTest.tileData(TEST_USER, flowOf(DataUpdateTrigger.InitialRequest)) + ) + runCurrent() + assertThat(dataList.map { it.isActivated }).containsExactly(false).inOrder() - // Add active mode - zenModeRepository.addMode(id = "One", active = true) - runCurrent() - assertThat(dataList.map { it.isActivated }).containsExactly(false, true).inOrder() + // Add active mode + zenModeRepository.addMode(id = "One", active = true) + runCurrent() + assertThat(dataList.map { it.isActivated }).containsExactly(false, true).inOrder() + assertThat(dataList.map { it.activeModes }.last()).containsExactly("Mode One") - // Add another mode: state hasn't changed, so this shouldn't cause another emission - zenModeRepository.addMode(id = "Two", active = true) - runCurrent() - assertThat(dataList.map { it.isActivated }).containsExactly(false, true).inOrder() + // Add an inactive mode: state hasn't changed, so this shouldn't cause another emission + zenModeRepository.addMode(id = "Two", active = false) + runCurrent() + assertThat(dataList.map { it.isActivated }).containsExactly(false, true).inOrder() + assertThat(dataList.map { it.activeModes }.last()).containsExactly("Mode One") - // Remove a mode and disable the other - zenModeRepository.removeMode("One") - runCurrent() - zenModeRepository.deactivateMode("Two") - runCurrent() - assertThat(dataList.map { it.isActivated }).containsExactly(false, true, false).inOrder() - } + // Add another active mode + zenModeRepository.addMode(id = "Three", active = true) + runCurrent() + assertThat(dataList.map { it.isActivated }).containsExactly(false, true, true).inOrder() + assertThat(dataList.map { it.activeModes }.last()) + .containsExactly("Mode One", "Mode Three") + .inOrder() + + // Remove a mode and deactivate the other + zenModeRepository.removeMode("One") + runCurrent() + zenModeRepository.deactivateMode("Three") + runCurrent() + assertThat(dataList.map { it.isActivated }) + .containsExactly(false, true, true, true, false) + .inOrder() + assertThat(dataList.map { it.activeModes }.last()).isEmpty() + } private companion object { diff --git a/packages/SystemUI/multivalentTests/src/com/android/systemui/qs/tiles/impl/modes/domain/interactor/ModesTileUserActionInteractorTest.kt b/packages/SystemUI/multivalentTests/src/com/android/systemui/qs/tiles/impl/modes/domain/interactor/ModesTileUserActionInteractorTest.kt index a67e7c6e84c5..4b7564981855 100644 --- a/packages/SystemUI/multivalentTests/src/com/android/systemui/qs/tiles/impl/modes/domain/interactor/ModesTileUserActionInteractorTest.kt +++ b/packages/SystemUI/multivalentTests/src/com/android/systemui/qs/tiles/impl/modes/domain/interactor/ModesTileUserActionInteractorTest.kt @@ -54,7 +54,11 @@ class ModesTileUserActionInteractorTest : SysuiTestCase() { fun handleClick_active() = runTest { val expandable = mock<Expandable>() underTest.handleInput( - QSTileInputTestKtx.click(data = ModesTileModel(true), expandable = expandable)) + QSTileInputTestKtx.click( + data = ModesTileModel(true, listOf("DND")), + expandable = expandable + ) + ) verify(mockDialogDelegate).showDialog(eq(expandable)) } @@ -63,14 +67,18 @@ class ModesTileUserActionInteractorTest : SysuiTestCase() { fun handleClick_inactive() = runTest { val expandable = mock<Expandable>() underTest.handleInput( - QSTileInputTestKtx.click(data = ModesTileModel(false), expandable = expandable)) + QSTileInputTestKtx.click( + data = ModesTileModel(false, emptyList()), + expandable = expandable + ) + ) verify(mockDialogDelegate).showDialog(eq(expandable)) } @Test fun handleLongClick_active() = runTest { - underTest.handleInput(QSTileInputTestKtx.longClick(ModesTileModel(true))) + underTest.handleInput(QSTileInputTestKtx.longClick(ModesTileModel(true, listOf("DND")))) QSTileIntentUserInputHandlerSubject.assertThat(inputHandler).handledOneIntentInput { assertThat(it.intent.action).isEqualTo(Settings.ACTION_ZEN_MODE_SETTINGS) @@ -79,7 +87,7 @@ class ModesTileUserActionInteractorTest : SysuiTestCase() { @Test fun handleLongClick_inactive() = runTest { - underTest.handleInput(QSTileInputTestKtx.longClick(ModesTileModel(false))) + underTest.handleInput(QSTileInputTestKtx.longClick(ModesTileModel(false, emptyList()))) QSTileIntentUserInputHandlerSubject.assertThat(inputHandler).handledOneIntentInput { assertThat(it.intent.action).isEqualTo(Settings.ACTION_ZEN_MODE_SETTINGS) diff --git a/packages/SystemUI/multivalentTests/src/com/android/systemui/qs/tiles/impl/modes/ui/ModesTileMapperTest.kt b/packages/SystemUI/multivalentTests/src/com/android/systemui/qs/tiles/impl/modes/ui/ModesTileMapperTest.kt index 3baf2f40f175..dd9711e50779 100644 --- a/packages/SystemUI/multivalentTests/src/com/android/systemui/qs/tiles/impl/modes/ui/ModesTileMapperTest.kt +++ b/packages/SystemUI/multivalentTests/src/com/android/systemui/qs/tiles/impl/modes/ui/ModesTileMapperTest.kt @@ -54,21 +54,35 @@ class ModesTileMapperTest : SysuiTestCase() { @Test fun inactiveState() { - val model = ModesTileModel(isActivated = false) + val model = ModesTileModel(isActivated = false, activeModes = emptyList()) val state = underTest.map(config, model) assertThat(state.activationState).isEqualTo(QSTileState.ActivationState.INACTIVE) assertThat(state.iconRes).isEqualTo(R.drawable.qs_dnd_icon_off) + assertThat(state.secondaryLabel).isEqualTo("No active modes") } @Test - fun activeState() { - val model = ModesTileModel(isActivated = true) + fun activeState_oneMode() { + val model = ModesTileModel(isActivated = true, activeModes = listOf("DND")) val state = underTest.map(config, model) assertThat(state.activationState).isEqualTo(QSTileState.ActivationState.ACTIVE) assertThat(state.iconRes).isEqualTo(R.drawable.qs_dnd_icon_on) + assertThat(state.secondaryLabel).isEqualTo("DND is active") + } + + @Test + fun activeState_multipleModes() { + val model = + ModesTileModel(isActivated = true, activeModes = listOf("Mode 1", "Mode 2", "Mode 3")) + + val state = underTest.map(config, model) + + assertThat(state.activationState).isEqualTo(QSTileState.ActivationState.ACTIVE) + assertThat(state.iconRes).isEqualTo(R.drawable.qs_dnd_icon_on) + assertThat(state.secondaryLabel).isEqualTo("3 modes are active") } } diff --git a/packages/SystemUI/multivalentTests/src/com/android/systemui/qs/ui/adapter/QSSceneAdapterImplTest.kt b/packages/SystemUI/multivalentTests/src/com/android/systemui/qs/ui/adapter/QSSceneAdapterImplTest.kt index 09580c5f17be..d472d98c03d4 100644 --- a/packages/SystemUI/multivalentTests/src/com/android/systemui/qs/ui/adapter/QSSceneAdapterImplTest.kt +++ b/packages/SystemUI/multivalentTests/src/com/android/systemui/qs/ui/adapter/QSSceneAdapterImplTest.kt @@ -24,9 +24,11 @@ import androidx.asynclayoutinflater.view.AsyncLayoutInflater import androidx.test.ext.junit.runners.AndroidJUnit4 import androidx.test.filters.SmallTest import com.android.systemui.SysuiTestCase +import com.android.systemui.biometrics.domain.interactor.displayStateInteractor import com.android.systemui.common.ui.data.repository.FakeConfigurationRepository import com.android.systemui.common.ui.domain.interactor.ConfigurationInteractor import com.android.systemui.coroutines.collectLastValue +import com.android.systemui.display.data.repository.displayStateRepository import com.android.systemui.dump.DumpManager import com.android.systemui.kosmos.Kosmos import com.android.systemui.kosmos.testCase @@ -117,6 +119,7 @@ class QSSceneAdapterImplTest : SysuiTestCase() { } private val shadeInteractor = kosmos.shadeInteractor + private val displayStateInteractor = kosmos.displayStateInteractor private val dumpManager = mock<DumpManager>() private val underTest = @@ -124,6 +127,7 @@ class QSSceneAdapterImplTest : SysuiTestCase() { qsSceneComponentFactory, qsImplProvider, shadeInteractor, + displayStateInteractor, dumpManager, testDispatcher, testScope.backgroundScope, @@ -583,6 +587,25 @@ class QSSceneAdapterImplTest : SysuiTestCase() { } @Test + fun setIsNotificationPanelFullWidth() = + testScope.runTest { + val qsImpl by collectLastValue(underTest.qsImpl) + + underTest.inflate(context) + runCurrent() + + kosmos.displayStateRepository.setIsLargeScreen(true) + runCurrent() + + verify(qsImpl!!).setIsNotificationPanelFullWidth(false) + + underTest.inflate(context) + runCurrent() + + verify(qsImpl!!).setIsNotificationPanelFullWidth(false) + } + + @Test fun setBrightnessMirrorController() = testScope.runTest { val qsImpl by collectLastValue(underTest.qsImpl) diff --git a/packages/SystemUI/multivalentTests/src/com/android/systemui/shade/NotificationShadeWindowControllerImplTest.java b/packages/SystemUI/multivalentTests/src/com/android/systemui/shade/NotificationShadeWindowControllerImplTest.java index 636d5a7dec06..34fbcacea683 100644 --- a/packages/SystemUI/multivalentTests/src/com/android/systemui/shade/NotificationShadeWindowControllerImplTest.java +++ b/packages/SystemUI/multivalentTests/src/com/android/systemui/shade/NotificationShadeWindowControllerImplTest.java @@ -46,6 +46,7 @@ import android.view.WindowManager; import androidx.test.filters.SmallTest; +import com.android.app.viewcapture.ViewCaptureAwareWindowManager; import com.android.internal.colorextraction.ColorExtractor; import com.android.systemui.SysuiTestCase; import com.android.systemui.biometrics.AuthController; @@ -59,6 +60,7 @@ import com.android.systemui.plugins.statusbar.StatusBarStateController; import com.android.systemui.res.R; import com.android.systemui.scene.FakeWindowRootViewComponent; import com.android.systemui.settings.UserTracker; +import com.android.systemui.shade.ui.viewmodel.NotificationShadeWindowModel; import com.android.systemui.statusbar.StatusBarState; import com.android.systemui.statusbar.SysuiStatusBarStateController; import com.android.systemui.statusbar.phone.DozeParameters; @@ -89,7 +91,7 @@ import platform.test.runner.parameterized.Parameters; @RunWithLooper(setAsMainLooper = true) @SmallTest public class NotificationShadeWindowControllerImplTest extends SysuiTestCase { - @Mock private WindowManager mWindowManager; + @Mock private ViewCaptureAwareWindowManager mWindowManager; @Mock private DozeParameters mDozeParameters; @Spy private final NotificationShadeWindowView mNotificationShadeWindowView = spy( new NotificationShadeWindowView(mContext, null)); @@ -105,6 +107,7 @@ public class NotificationShadeWindowControllerImplTest extends SysuiTestCase { @Mock private ShadeWindowLogger mShadeWindowLogger; @Mock private SelectedUserInteractor mSelectedUserInteractor; @Mock private UserTracker mUserTracker; + @Mock private NotificationShadeWindowModel mNotificationShadeWindowModel; @Captor private ArgumentCaptor<WindowManager.LayoutParams> mLayoutParameters; @Captor private ArgumentCaptor<StatusBarStateController.StateListener> mStateListener; @@ -160,6 +163,7 @@ public class NotificationShadeWindowControllerImplTest extends SysuiTestCase { mShadeWindowLogger, () -> mSelectedUserInteractor, mUserTracker, + mNotificationShadeWindowModel, mKosmos::getCommunalInteractor) { @Override protected boolean isDebuggable() { diff --git a/packages/SystemUI/multivalentTests/src/com/android/systemui/shade/domain/startable/ShadeStartableTest.kt b/packages/SystemUI/multivalentTests/src/com/android/systemui/shade/domain/startable/ShadeStartableTest.kt index cecc70cae60d..d37e0fb2f047 100644 --- a/packages/SystemUI/multivalentTests/src/com/android/systemui/shade/domain/startable/ShadeStartableTest.kt +++ b/packages/SystemUI/multivalentTests/src/com/android/systemui/shade/domain/startable/ShadeStartableTest.kt @@ -27,6 +27,7 @@ import com.android.systemui.authentication.data.repository.fakeAuthenticationRep import com.android.systemui.authentication.shared.model.AuthenticationMethodModel import com.android.systemui.common.ui.data.repository.fakeConfigurationRepository import com.android.systemui.coroutines.collectLastValue +import com.android.systemui.display.data.repository.displayStateRepository import com.android.systemui.flags.EnableSceneContainer import com.android.systemui.flags.parameterizeSceneContainerFlag import com.android.systemui.keyguard.data.repository.fakeDeviceEntryFingerprintAuthRepository @@ -41,6 +42,8 @@ import com.android.systemui.shade.ShadeExpansionListener import com.android.systemui.shade.domain.interactor.shadeInteractor import com.android.systemui.shade.shared.flag.DualShade import com.android.systemui.shade.shared.model.ShadeMode +import com.android.systemui.statusbar.notification.stack.notificationStackScrollLayoutController +import com.android.systemui.statusbar.phone.scrimController import com.android.systemui.testKosmos import com.android.systemui.util.mockito.any import com.android.systemui.util.mockito.mock @@ -54,6 +57,7 @@ import kotlinx.coroutines.test.runCurrent import kotlinx.coroutines.test.runTest import org.junit.Test import org.junit.runner.RunWith +import org.mockito.kotlin.verify import platform.test.runner.parameterized.ParameterizedAndroidJunit4 import platform.test.runner.parameterized.Parameters @@ -167,6 +171,18 @@ class ShadeStartableTest(flags: FlagsParameterization) : SysuiTestCase() { } } + @Test + @EnableSceneContainer + fun hydrateFullWidth() = + testScope.runTest { + underTest.start() + + kosmos.displayStateRepository.setIsLargeScreen(true) + runCurrent() + verify(kosmos.notificationStackScrollLayoutController).setIsFullWidth(false) + assertThat(kosmos.scrimController.clipQsScrim).isFalse() + } + private fun TestScope.changeScene( toScene: SceneKey, transitionState: MutableStateFlow<ObservableTransitionState>, diff --git a/packages/SystemUI/multivalentTests/src/com/android/systemui/shade/ui/viewmodel/NotificationShadeWindowModelTest.kt b/packages/SystemUI/multivalentTests/src/com/android/systemui/shade/ui/viewmodel/NotificationShadeWindowModelTest.kt new file mode 100644 index 000000000000..add33dacf669 --- /dev/null +++ b/packages/SystemUI/multivalentTests/src/com/android/systemui/shade/ui/viewmodel/NotificationShadeWindowModelTest.kt @@ -0,0 +1,65 @@ +/* + * Copyright (C) 2024 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.android.systemui.shade.ui.viewmodel + +import androidx.test.ext.junit.runners.AndroidJUnit4 +import androidx.test.filters.SmallTest +import com.android.systemui.SysuiTestCase +import com.android.systemui.coroutines.collectLastValue +import com.android.systemui.keyguard.data.repository.fakeKeyguardTransitionRepository +import com.android.systemui.keyguard.shared.model.KeyguardState +import com.android.systemui.kosmos.testScope +import com.android.systemui.testKosmos +import com.google.common.truth.Truth.assertThat +import kotlinx.coroutines.ExperimentalCoroutinesApi +import kotlinx.coroutines.test.runTest +import org.junit.Test +import org.junit.runner.RunWith + +@OptIn(ExperimentalCoroutinesApi::class) +@SmallTest +@RunWith(AndroidJUnit4::class) +class NotificationShadeWindowModelTest : SysuiTestCase() { + + private val kosmos = testKosmos() + private val testScope = kosmos.testScope + private val keyguardTransitionRepository by lazy { kosmos.fakeKeyguardTransitionRepository } + private val underTest: NotificationShadeWindowModel by lazy { + kosmos.notificationShadeWindowModel + } + + @Test + fun transitionToOccluded() = + testScope.runTest { + val isKeyguardOccluded by collectLastValue(underTest.isKeyguardOccluded) + assertThat(isKeyguardOccluded).isFalse() + + keyguardTransitionRepository.sendTransitionSteps( + from = KeyguardState.LOCKSCREEN, + to = KeyguardState.OCCLUDED, + testScope, + ) + assertThat(isKeyguardOccluded).isTrue() + + keyguardTransitionRepository.sendTransitionSteps( + from = KeyguardState.OCCLUDED, + to = KeyguardState.GONE, + testScope, + ) + assertThat(isKeyguardOccluded).isFalse() + } +} diff --git a/packages/SystemUI/multivalentTests/src/com/android/systemui/statusbar/notification/stack/ui/viewmodel/SharedNotificationContainerViewModelTest.kt b/packages/SystemUI/multivalentTests/src/com/android/systemui/statusbar/notification/stack/ui/viewmodel/SharedNotificationContainerViewModelTest.kt index 6f099310f9f7..9fea7a2bfbf6 100644 --- a/packages/SystemUI/multivalentTests/src/com/android/systemui/statusbar/notification/stack/ui/viewmodel/SharedNotificationContainerViewModelTest.kt +++ b/packages/SystemUI/multivalentTests/src/com/android/systemui/statusbar/notification/stack/ui/viewmodel/SharedNotificationContainerViewModelTest.kt @@ -19,12 +19,10 @@ package com.android.systemui.statusbar.notification.stack.ui.viewmodel -import android.platform.test.annotations.DisableFlags import android.platform.test.annotations.EnableFlags import android.platform.test.flag.junit.FlagsParameterization import androidx.test.filters.SmallTest import com.android.compose.animation.scene.ObservableTransitionState -import com.android.systemui.Flags.FLAG_CENTRALIZED_STATUS_BAR_HEIGHT_FIX import com.android.systemui.Flags.FLAG_MIGRATE_CLOCKS_TO_BLUEPRINT import com.android.systemui.SysuiTestCase import com.android.systemui.bouncer.data.repository.keyguardBouncerRepository @@ -38,8 +36,8 @@ import com.android.systemui.flags.BrokenWithSceneContainer import com.android.systemui.flags.DisableSceneContainer import com.android.systemui.flags.EnableSceneContainer import com.android.systemui.flags.Flags -import com.android.systemui.flags.andSceneContainer import com.android.systemui.flags.fakeFeatureFlagsClassic +import com.android.systemui.flags.parameterizeSceneContainerFlag import com.android.systemui.keyguard.data.repository.fakeKeyguardRepository import com.android.systemui.keyguard.data.repository.fakeKeyguardTransitionRepository import com.android.systemui.keyguard.domain.interactor.keyguardInteractor @@ -60,7 +58,6 @@ import com.android.systemui.kosmos.testScope import com.android.systemui.res.R import com.android.systemui.shade.mockLargeScreenHeaderHelper import com.android.systemui.shade.shadeTestUtil -import com.android.systemui.statusbar.notification.NotificationUtils.interpolate import com.android.systemui.statusbar.notification.stack.domain.interactor.sharedNotificationContainerInteractor import com.android.systemui.testKosmos import com.android.systemui.util.mockito.any @@ -90,10 +87,7 @@ class SharedNotificationContainerViewModelTest(flags: FlagsParameterization) : S @JvmStatic @Parameters(name = "{0}") fun getParams(): List<FlagsParameterization> { - return FlagsParameterization.allCombinationsOf( - FLAG_CENTRALIZED_STATUS_BAR_HEIGHT_FIX, - ) - .andSceneContainer() + return parameterizeSceneContainerFlag() } } @@ -178,25 +172,6 @@ class SharedNotificationContainerViewModelTest(flags: FlagsParameterization) : S } @Test - @DisableFlags(FLAG_CENTRALIZED_STATUS_BAR_HEIGHT_FIX) - fun validatePaddingTopInSplitShade_refactorFlagOff_usesLargeHeaderResource() = - testScope.runTest { - whenever(largeScreenHeaderHelper.getLargeScreenHeaderHeight()).thenReturn(5) - overrideResource(R.bool.config_use_split_notification_shade, true) - overrideResource(R.bool.config_use_large_screen_shade_header, true) - overrideResource(R.dimen.large_screen_shade_header_height, 10) - overrideResource(R.dimen.keyguard_split_shade_top_margin, 50) - - val paddingTop by collectLastValue(underTest.paddingTopDimen) - - configurationRepository.onAnyConfigurationChange() - - // Should directly use the header height (flagged off value) - assertThat(paddingTop).isEqualTo(10) - } - - @Test - @EnableFlags(FLAG_CENTRALIZED_STATUS_BAR_HEIGHT_FIX) fun validatePaddingTopInSplitShade_refactorFlagOn_usesLargeHeaderHelper() = testScope.runTest { whenever(largeScreenHeaderHelper.getLargeScreenHeaderHeight()).thenReturn(5) @@ -268,49 +243,8 @@ class SharedNotificationContainerViewModelTest(flags: FlagsParameterization) : S } @Test - @DisableFlags(FLAG_CENTRALIZED_STATUS_BAR_HEIGHT_FIX) - @DisableSceneContainer - fun validateMarginTopWithLargeScreenHeader_refactorFlagOff_usesResource() = - testScope.runTest { - val headerResourceHeight = 50 - val headerHelperHeight = 100 - whenever(largeScreenHeaderHelper.getLargeScreenHeaderHeight()) - .thenReturn(headerHelperHeight) - overrideResource(R.bool.config_use_large_screen_shade_header, true) - overrideResource(R.dimen.large_screen_shade_header_height, headerResourceHeight) - overrideResource(R.dimen.notification_panel_margin_top, 0) - - val dimens by collectLastValue(underTest.configurationBasedDimensions) - - configurationRepository.onAnyConfigurationChange() - - assertThat(dimens!!.marginTop).isEqualTo(headerResourceHeight) - } - - @Test - @DisableFlags(FLAG_CENTRALIZED_STATUS_BAR_HEIGHT_FIX) - @EnableSceneContainer - fun validateMarginTopWithLargeScreenHeader_refactorFlagOff_sceneContainerFlagOn_stillZero() = - testScope.runTest { - val headerResourceHeight = 50 - val headerHelperHeight = 100 - whenever(largeScreenHeaderHelper.getLargeScreenHeaderHeight()) - .thenReturn(headerHelperHeight) - overrideResource(R.bool.config_use_large_screen_shade_header, true) - overrideResource(R.dimen.large_screen_shade_header_height, headerResourceHeight) - overrideResource(R.dimen.notification_panel_margin_top, 0) - - val dimens by collectLastValue(underTest.configurationBasedDimensions) - - configurationRepository.onAnyConfigurationChange() - - assertThat(dimens!!.marginTop).isEqualTo(0) - } - - @Test @DisableSceneContainer - @EnableFlags(FLAG_CENTRALIZED_STATUS_BAR_HEIGHT_FIX) - fun validateMarginTopWithLargeScreenHeader_refactorFlagOn_usesHelper() = + fun validateMarginTopWithLargeScreenHeader_usesHelper() = testScope.runTest { val headerResourceHeight = 50 val headerHelperHeight = 100 @@ -329,7 +263,6 @@ class SharedNotificationContainerViewModelTest(flags: FlagsParameterization) : S @Test @EnableSceneContainer - @EnableFlags(FLAG_CENTRALIZED_STATUS_BAR_HEIGHT_FIX) fun validateMarginTopWithLargeScreenHeader_sceneContainerFlagOn_stillZero() = testScope.runTest { val headerResourceHeight = 50 @@ -590,44 +523,45 @@ class SharedNotificationContainerViewModelTest(flags: FlagsParameterization) : S } @Test - @DisableFlags(FLAG_CENTRALIZED_STATUS_BAR_HEIGHT_FIX) @DisableSceneContainer - fun boundsOnLockscreenInSplitShade_refactorFlagOff_usesLargeHeaderResource() = + fun boundsDoNotChangeWhileLockscreenToAodTransitionIsActive() = testScope.runTest { val bounds by collectLastValue(underTest.bounds) - // When in split shade - whenever(largeScreenHeaderHelper.getLargeScreenHeaderHeight()).thenReturn(5) - overrideResource(R.bool.config_use_split_notification_shade, true) - overrideResource(R.bool.config_use_large_screen_shade_header, true) - overrideResource(R.dimen.large_screen_shade_header_height, 10) - overrideResource(R.dimen.keyguard_split_shade_top_margin, 50) - - configurationRepository.onAnyConfigurationChange() - runCurrent() - // Start on lockscreen showLockscreen() keyguardInteractor.setNotificationContainerBounds( - NotificationContainerBounds(top = 1f, bottom = 52f) + NotificationContainerBounds(top = 1f, bottom = 1f) + ) + assertThat(bounds).isEqualTo(NotificationContainerBounds(top = 1f, bottom = 1f)) + + // Begin transition to AOD + keyguardTransitionRepository.sendTransitionStep( + TransitionStep(LOCKSCREEN, AOD, 0f, TransitionState.STARTED) ) runCurrent() + keyguardTransitionRepository.sendTransitionStep( + TransitionStep(LOCKSCREEN, AOD, 0.5f, TransitionState.RUNNING) + ) - // Top should be equal to bounds (1) - padding adjustment (10) - assertThat(bounds) - .isEqualTo( - NotificationContainerBounds( - top = -9f, - bottom = 2f, - ) - ) + // Attempt to update bounds + keyguardInteractor.setNotificationContainerBounds( + NotificationContainerBounds(top = 5f, bottom = 5f) + ) + // Bounds should not have moved + assertThat(bounds).isEqualTo(NotificationContainerBounds(top = 1f, bottom = 1f)) + + // Transition is over, now move + keyguardTransitionRepository.sendTransitionStep( + TransitionStep(LOCKSCREEN, AOD, 1f, TransitionState.FINISHED) + ) + assertThat(bounds).isEqualTo(NotificationContainerBounds(top = 5f, bottom = 5f)) } @Test - @EnableFlags(FLAG_CENTRALIZED_STATUS_BAR_HEIGHT_FIX) @DisableSceneContainer - fun boundsOnLockscreenInSplitShade_refactorFlagOn_usesLargeHeaderHelper() = + fun boundsOnLockscreenInSplitShade_usesLargeHeaderHelper() = testScope.runTest { val bounds by collectLastValue(underTest.bounds) @@ -820,54 +754,6 @@ class SharedNotificationContainerViewModelTest(flags: FlagsParameterization) : S @Test @DisableSceneContainer - fun updateBounds_fromKeyguardRoot() = - testScope.runTest { - val startProgress = 0f - val startStep = TransitionStep(LOCKSCREEN, AOD, startProgress, TransitionState.STARTED) - val boundsChangingProgress = 0.2f - val boundsChangingStep = - TransitionStep(LOCKSCREEN, AOD, boundsChangingProgress, TransitionState.RUNNING) - val boundsInterpolatingProgress = 0.6f - val boundsInterpolatingStep = - TransitionStep( - LOCKSCREEN, - AOD, - boundsInterpolatingProgress, - TransitionState.RUNNING - ) - val finishProgress = 1.0f - val finishStep = - TransitionStep(LOCKSCREEN, AOD, finishProgress, TransitionState.FINISHED) - - val bounds by collectLastValue(underTest.bounds) - val top = 123f - val bottom = 456f - - kosmos.fakeKeyguardTransitionRepository.sendTransitionStep(startStep) - runCurrent() - kosmos.fakeKeyguardTransitionRepository.sendTransitionStep(boundsChangingStep) - runCurrent() - keyguardRootViewModel.onNotificationContainerBoundsChanged(top, bottom) - - kosmos.fakeKeyguardTransitionRepository.sendTransitionStep(boundsInterpolatingStep) - runCurrent() - val adjustedProgress = - (boundsInterpolatingProgress - boundsChangingProgress) / - (1 - boundsChangingProgress) - val interpolatedTop = interpolate(0f, top, adjustedProgress) - val interpolatedBottom = interpolate(0f, bottom, adjustedProgress) - assertThat(bounds) - .isEqualTo( - NotificationContainerBounds(top = interpolatedTop, bottom = interpolatedBottom) - ) - - kosmos.fakeKeyguardTransitionRepository.sendTransitionStep(finishStep) - runCurrent() - assertThat(bounds).isEqualTo(NotificationContainerBounds(top = top, bottom = bottom)) - } - - @Test - @DisableSceneContainer fun updateBounds_fromGone_withoutTransitions() = testScope.runTest { // Start step is already at 1.0 @@ -878,9 +764,9 @@ class SharedNotificationContainerViewModelTest(flags: FlagsParameterization) : S val top = 123f val bottom = 456f - kosmos.fakeKeyguardTransitionRepository.sendTransitionStep(runningStep) + keyguardTransitionRepository.sendTransitionStep(runningStep) runCurrent() - kosmos.fakeKeyguardTransitionRepository.sendTransitionStep(finishStep) + keyguardTransitionRepository.sendTransitionStep(finishStep) runCurrent() keyguardRootViewModel.onNotificationContainerBoundsChanged(top, bottom) runCurrent() diff --git a/packages/SystemUI/multivalentTests/src/com/android/systemui/statusbar/policy/domain/interactor/ZenModeInteractorTest.kt b/packages/SystemUI/multivalentTests/src/com/android/systemui/statusbar/policy/domain/interactor/ZenModeInteractorTest.kt index 88431f004665..32f66c1ccd66 100644 --- a/packages/SystemUI/multivalentTests/src/com/android/systemui/statusbar/policy/domain/interactor/ZenModeInteractorTest.kt +++ b/packages/SystemUI/multivalentTests/src/com/android/systemui/statusbar/policy/domain/interactor/ZenModeInteractorTest.kt @@ -18,15 +18,21 @@ package com.android.systemui.statusbar.policy.domain.interactor import android.app.NotificationManager.Policy import android.provider.Settings +import android.provider.Settings.Secure.ZEN_DURATION +import android.provider.Settings.Secure.ZEN_DURATION_FOREVER +import android.provider.Settings.Secure.ZEN_DURATION_PROMPT import androidx.test.ext.junit.runners.AndroidJUnit4 import androidx.test.filters.SmallTest import com.android.settingslib.notification.data.repository.updateNotificationPolicy +import com.android.settingslib.notification.modes.TestModeBuilder import com.android.systemui.SysuiTestCase import com.android.systemui.coroutines.collectLastValue import com.android.systemui.kosmos.testScope +import com.android.systemui.shared.settings.data.repository.secureSettingsRepository import com.android.systemui.statusbar.policy.data.repository.fakeZenModeRepository import com.android.systemui.testKosmos import com.google.common.truth.Truth.assertThat +import java.time.Duration import kotlinx.coroutines.ExperimentalCoroutinesApi import kotlinx.coroutines.test.runCurrent import kotlinx.coroutines.test.runTest @@ -39,7 +45,8 @@ import org.junit.runner.RunWith class ZenModeInteractorTest : SysuiTestCase() { private val kosmos = testKosmos() private val testScope = kosmos.testScope - private val repository = kosmos.fakeZenModeRepository + private val zenModeRepository = kosmos.fakeZenModeRepository + private val settingsRepository = kosmos.secureSettingsRepository private val underTest = kosmos.zenModeInteractor @@ -48,7 +55,7 @@ class ZenModeInteractorTest : SysuiTestCase() { testScope.runTest { val enabled by collectLastValue(underTest.isZenModeEnabled) - repository.updateZenMode(Settings.Global.ZEN_MODE_OFF) + zenModeRepository.updateZenMode(Settings.Global.ZEN_MODE_OFF) runCurrent() assertThat(enabled).isFalse() @@ -59,7 +66,7 @@ class ZenModeInteractorTest : SysuiTestCase() { testScope.runTest { val enabled by collectLastValue(underTest.isZenModeEnabled) - repository.updateZenMode(Settings.Global.ZEN_MODE_ALARMS) + zenModeRepository.updateZenMode(Settings.Global.ZEN_MODE_ALARMS) runCurrent() assertThat(enabled).isTrue() @@ -70,7 +77,7 @@ class ZenModeInteractorTest : SysuiTestCase() { testScope.runTest { val enabled by collectLastValue(underTest.isZenModeEnabled) - repository.updateZenMode(Settings.Global.ZEN_MODE_IMPORTANT_INTERRUPTIONS) + zenModeRepository.updateZenMode(Settings.Global.ZEN_MODE_IMPORTANT_INTERRUPTIONS) runCurrent() assertThat(enabled).isTrue() @@ -81,7 +88,7 @@ class ZenModeInteractorTest : SysuiTestCase() { testScope.runTest { val enabled by collectLastValue(underTest.isZenModeEnabled) - repository.updateZenMode(Settings.Global.ZEN_MODE_NO_INTERRUPTIONS) + zenModeRepository.updateZenMode(Settings.Global.ZEN_MODE_NO_INTERRUPTIONS) runCurrent() assertThat(enabled).isTrue() @@ -92,7 +99,8 @@ class ZenModeInteractorTest : SysuiTestCase() { testScope.runTest { val enabled by collectLastValue(underTest.isZenModeEnabled) - repository.updateZenMode(4) // this should fail if we ever add another zen mode type + // this should fail if we ever add another zen mode type + zenModeRepository.updateZenMode(4) runCurrent() assertThat(enabled).isFalse() @@ -103,8 +111,8 @@ class ZenModeInteractorTest : SysuiTestCase() { testScope.runTest { val hidden by collectLastValue(underTest.areNotificationsHiddenInShade) - repository.updateNotificationPolicy(null) - repository.updateZenMode(Settings.Global.ZEN_MODE_IMPORTANT_INTERRUPTIONS) + zenModeRepository.updateNotificationPolicy(null) + zenModeRepository.updateZenMode(Settings.Global.ZEN_MODE_IMPORTANT_INTERRUPTIONS) runCurrent() assertThat(hidden).isFalse() @@ -115,10 +123,10 @@ class ZenModeInteractorTest : SysuiTestCase() { testScope.runTest { val hidden by collectLastValue(underTest.areNotificationsHiddenInShade) - repository.updateNotificationPolicy( + zenModeRepository.updateNotificationPolicy( suppressedVisualEffects = Policy.SUPPRESSED_EFFECT_NOTIFICATION_LIST ) - repository.updateZenMode(Settings.Global.ZEN_MODE_OFF) + zenModeRepository.updateZenMode(Settings.Global.ZEN_MODE_OFF) runCurrent() assertThat(hidden).isFalse() @@ -129,10 +137,10 @@ class ZenModeInteractorTest : SysuiTestCase() { testScope.runTest { val hidden by collectLastValue(underTest.areNotificationsHiddenInShade) - repository.updateNotificationPolicy( + zenModeRepository.updateNotificationPolicy( suppressedVisualEffects = Policy.SUPPRESSED_EFFECT_STATUS_BAR ) - repository.updateZenMode(Settings.Global.ZEN_MODE_IMPORTANT_INTERRUPTIONS) + zenModeRepository.updateZenMode(Settings.Global.ZEN_MODE_IMPORTANT_INTERRUPTIONS) runCurrent() assertThat(hidden).isFalse() @@ -143,12 +151,70 @@ class ZenModeInteractorTest : SysuiTestCase() { testScope.runTest { val hidden by collectLastValue(underTest.areNotificationsHiddenInShade) - repository.updateNotificationPolicy( + zenModeRepository.updateNotificationPolicy( suppressedVisualEffects = Policy.SUPPRESSED_EFFECT_NOTIFICATION_LIST ) - repository.updateZenMode(Settings.Global.ZEN_MODE_IMPORTANT_INTERRUPTIONS) + zenModeRepository.updateZenMode(Settings.Global.ZEN_MODE_IMPORTANT_INTERRUPTIONS) runCurrent() assertThat(hidden).isTrue() } + + @Test + fun shouldAskForZenDuration_falseForNonManualDnd() = + testScope.runTest { + settingsRepository.setInt(ZEN_DURATION, ZEN_DURATION_PROMPT) + runCurrent() + + assertThat(underTest.shouldAskForZenDuration(TestModeBuilder.EXAMPLE)).isFalse() + } + + @Test + fun shouldAskForZenDuration_changesWithSetting() = + testScope.runTest { + val manualDnd = TestModeBuilder.MANUAL_DND + + settingsRepository.setInt(ZEN_DURATION, ZEN_DURATION_FOREVER) + runCurrent() + + assertThat(underTest.shouldAskForZenDuration(manualDnd)).isFalse() + + settingsRepository.setInt(ZEN_DURATION, ZEN_DURATION_PROMPT) + runCurrent() + + assertThat(underTest.shouldAskForZenDuration(manualDnd)).isTrue() + } + + @Test + fun activateMode_nonManualDnd() = + testScope.runTest { + val mode = TestModeBuilder().setActive(false).build() + zenModeRepository.addModes(listOf(mode)) + settingsRepository.setInt(ZEN_DURATION, 60) + runCurrent() + + underTest.activateMode(mode) + assertThat(zenModeRepository.getMode(mode.id)?.isActive).isTrue() + assertThat(zenModeRepository.getModeActiveDuration(mode.id)).isNull() + } + + @Test + fun activateMode_usesCorrectDuration() = + testScope.runTest { + val manualDnd = TestModeBuilder.MANUAL_DND + zenModeRepository.addModes(listOf(manualDnd)) + settingsRepository.setInt(ZEN_DURATION, ZEN_DURATION_FOREVER) + runCurrent() + + underTest.activateMode(manualDnd) + assertThat(zenModeRepository.getModeActiveDuration(manualDnd.id)).isNull() + + zenModeRepository.deactivateMode(manualDnd.id) + settingsRepository.setInt(ZEN_DURATION, 60) + runCurrent() + + underTest.activateMode(manualDnd) + assertThat(zenModeRepository.getModeActiveDuration(manualDnd.id)) + .isEqualTo(Duration.ofMinutes(60)) + } } diff --git a/packages/SystemUI/multivalentTests/src/com/android/systemui/volume/domain/interactor/AudioSharingInteractorTest.kt b/packages/SystemUI/multivalentTests/src/com/android/systemui/volume/domain/interactor/AudioSharingInteractorTest.kt index 142631e6aa07..a1fcfcd0f749 100644 --- a/packages/SystemUI/multivalentTests/src/com/android/systemui/volume/domain/interactor/AudioSharingInteractorTest.kt +++ b/packages/SystemUI/multivalentTests/src/com/android/systemui/volume/domain/interactor/AudioSharingInteractorTest.kt @@ -16,8 +16,10 @@ package com.android.systemui.volume.domain.interactor +import android.media.AudioManager.STREAM_MUSIC import androidx.test.ext.junit.runners.AndroidJUnit4 import androidx.test.filters.SmallTest +import com.android.settingslib.volume.shared.model.AudioStream import com.android.systemui.SysuiTestCase import com.android.systemui.coroutines.collectLastValue import com.android.systemui.kosmos.testScope @@ -40,17 +42,57 @@ class AudioSharingInteractorTest : SysuiTestCase() { @Before fun setUp() { - with(kosmos) { underTest = audioSharingInteractor } + with(kosmos) { + with(audioSharingRepository) { setVolumeMap(mapOf(TEST_GROUP_ID to TEST_VOLUME)) } + underTest = audioSharingInteractor + } } @Test - fun volumeChanges_returnVolume() { + fun handlePrimaryGroupChange_nullVolume() { with(kosmos) { testScope.runTest { - with(audioSharingRepository) { - setSecondaryGroupId(TEST_GROUP_ID) - setVolumeMap(mapOf(TEST_GROUP_ID to TEST_VOLUME)) - } + with(audioSharingRepository) { setPrimaryGroupId(TEST_GROUP_ID_INVALID) } + val preMusicStream by + collectLastValue( + audioVolumeInteractor.getAudioStream(AudioStream(STREAM_MUSIC)) + ) + val preVolume = preMusicStream?.volume + runCurrent() + underTest.handlePrimaryGroupChange() + val musicStream by + collectLastValue( + audioVolumeInteractor.getAudioStream(AudioStream(STREAM_MUSIC)) + ) + runCurrent() + + Truth.assertThat(musicStream?.volume).isEqualTo(preVolume) + } + } + } + + @Test + fun handlePrimaryGroupChange_setStreamVolume() { + with(kosmos) { + testScope.runTest { + with(audioSharingRepository) { setPrimaryGroupId(TEST_GROUP_ID) } + underTest.handlePrimaryGroupChange() + val musicStream by + collectLastValue( + audioVolumeInteractor.getAudioStream(AudioStream(STREAM_MUSIC)) + ) + runCurrent() + + Truth.assertThat(musicStream?.volume).isEqualTo(TEST_MUSIC_VOLUME) + } + } + } + + @Test + fun secondaryGroupVolumeChanges_returnVolume() { + with(kosmos) { + testScope.runTest { + with(audioSharingRepository) { setSecondaryGroupId(TEST_GROUP_ID) } val volume by collectLastValue(underTest.volume) runCurrent() @@ -60,13 +102,10 @@ class AudioSharingInteractorTest : SysuiTestCase() { } @Test - fun volumeChanges_returnNull() { + fun secondaryGroupVolumeChanges_returnNull() { with(kosmos) { testScope.runTest { - with(audioSharingRepository) { - setSecondaryGroupId(TEST_GROUP_ID_INVALID) - setVolumeMap(mapOf(TEST_GROUP_ID to TEST_VOLUME)) - } + with(audioSharingRepository) { setSecondaryGroupId(TEST_GROUP_ID_INVALID) } val volume by collectLastValue(underTest.volume) runCurrent() @@ -76,7 +115,7 @@ class AudioSharingInteractorTest : SysuiTestCase() { } @Test - fun volumeChanges_returnDefaultVolume() { + fun secondaryGroupVolumeChanges_returnDefaultVolume() { with(kosmos) { testScope.runTest { with(audioSharingRepository) { @@ -94,7 +133,8 @@ class AudioSharingInteractorTest : SysuiTestCase() { private companion object { const val TEST_GROUP_ID = 1 const val TEST_GROUP_ID_INVALID = -1 - const val TEST_VOLUME = 10 + const val TEST_MUSIC_VOLUME = 10 + const val TEST_VOLUME = 255 const val TEST_VOLUME_DEFAULT = 20 } } diff --git a/packages/SystemUI/res/drawable/brightness_bar.xml b/packages/SystemUI/res/drawable/brightness_bar.xml new file mode 100644 index 000000000000..2afe164ab5c5 --- /dev/null +++ b/packages/SystemUI/res/drawable/brightness_bar.xml @@ -0,0 +1,36 @@ +<!-- + ~ Copyright (C) 2024 The Android Open Source Project + ~ + ~ Licensed under the Apache License, Version 2.0 (the "License"); + ~ you may not use this file except in compliance with the License. + ~ You may obtain a copy of the License at + ~ + ~ http://www.apache.org/licenses/LICENSE-2.0 + ~ + ~ Unless required by applicable law or agreed to in writing, software + ~ distributed under the License is distributed on an "AS IS" BASIS, + ~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + ~ See the License for the specific language governing permissions and + ~ limitations under the License. + --> +<vector xmlns:android="http://schemas.android.com/apk/res/android" + xmlns:androidprv="http://schemas.android.com/apk/prv/res/android" + android:width="200dp" + android:height="32dp" + android:viewportWidth="304" + android:viewportHeight="48"> +<path + android:pathData="M2,22L302,22A2,2 0,0 1,304 24L304,24A2,2 0,0 1,302 26L2,26A2,2 0,0 1,0 24L0,24A2,2 0,0 1,2 22z" + android:fillColor="@color/brightness_slider_track"/> +<path + android:pathData="M24,0L205.71,0A24,24 0,0 1,229.71 24L229.71,24A24,24 0,0 1,205.71 48L24,48A24,24 0,0 1,0 24L0,24A24,24 0,0 1,24 0z" + android:fillColor="?attr/shadeActive"/> +<path + android:pathData="M0,24C0,10.75 10.75,0 24,0H63.85V48H24C10.75,48 0,37.25 0,24Z" + android:fillColor="?androidprv:attr/colorAccentPrimaryVariant"/> +<path + android:pathData="M208.98,21.26V17.37H205.09L202.34,14.62L199.6,17.37H195.71V21.26L192.96,24L195.71,26.75V30.63H199.6L202.34,33.38L205.09,30.63H208.98V26.75L211.72,24L208.98,21.26ZM207.32,26.06V28.98H204.4L202.34,31.03L200.29,28.98H197.37V26.06L195.31,24L197.37,21.94V19.02H200.29L202.34,16.97L204.4,19.02H207.32V21.94L209.37,24L207.32,26.06ZM206.49,24C206.49,26.29 204.63,28.15 202.34,28.15V19.85C204.63,19.85 206.49,21.71 206.49,24Z" + android:fillColor="?attr/onShadeActive" + android:fillType="evenOdd"/> +</vector> + diff --git a/packages/SystemUI/res/layout/accessibility_deprecate_extra_dim_dialog.xml b/packages/SystemUI/res/layout/accessibility_deprecate_extra_dim_dialog.xml new file mode 100644 index 000000000000..e839f4c8ffd0 --- /dev/null +++ b/packages/SystemUI/res/layout/accessibility_deprecate_extra_dim_dialog.xml @@ -0,0 +1,41 @@ +<!-- + ~ Copyright (C) 2024 The Android Open Source Project + ~ + ~ Licensed under the Apache License, Version 2.0 (the "License"); + ~ you may not use this file except in compliance with the License. + ~ You may obtain a copy of the License at + ~ + ~ http://www.apache.org/licenses/LICENSE-2.0 + ~ + ~ Unless required by applicable law or agreed to in writing, software + ~ distributed under the License is distributed on an "AS IS" BASIS, + ~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + ~ See the License for the specific language governing permissions and + ~ limitations under the License. + --> +<LinearLayout + xmlns:android="http://schemas.android.com/apk/res/android" + android:id="@+id/illustration_frame" + android:orientation="vertical" + android:paddingHorizontal="16dp" + android:layout_width="match_parent" + android:layout_height="wrap_content" + android:layout_gravity="center"> + + <ImageView + android:layout_width="match_parent" + android:layout_height="match_parent" + android:adjustViewBounds="true" + android:layout_marginVertical="24dp" + android:scaleType="fitCenter" + android:importantForAccessibility="no" + android:theme="@style/Theme.SystemUI.QuickSettings" + android:src="@drawable/brightness_bar"/> + <TextView + android:layout_width="wrap_content" + android:layout_height="wrap_content" + android:layout_gravity="center" + android:textSize="16sp" + android:text="@string/accessibility_deprecate_extra_dim_dialog_description" + android:textAppearance="@style/TextAppearance.Dialog.Body"/> +</LinearLayout>
\ No newline at end of file diff --git a/packages/SystemUI/res/values-af/strings.xml b/packages/SystemUI/res/values-af/strings.xml index d5ca85c0e75b..8c685ffda2f7 100644 --- a/packages/SystemUI/res/values-af/strings.xml +++ b/packages/SystemUI/res/values-af/strings.xml @@ -388,6 +388,9 @@ <string name="performance" msgid="6552785217174378320">"Werkverrigting"</string> <string name="user_interface" msgid="3712869377953950887">"Gebruikerkoppelvlak"</string> <string name="thermal" msgid="6758074791325414831">"Termies"</string> + <string name="custom" msgid="3337456985275158299">"Gepasmaak"</string> + <string name="custom_trace_settings_dialog_title" msgid="2608570500144830554">"Gepasmaakte Nasporinginstellings"</string> + <string name="restore_default" msgid="5259420807486239755">"Stel verstek terug"</string> <string name="quick_settings_onehanded_label" msgid="2416537930246274991">"Eenhandmodus"</string> <string name="quick_settings_hearing_devices_label" msgid="7277170419679404129">"Gehoortoestelle"</string> <string name="quick_settings_hearing_devices_connected" msgid="6519069502397037781">"Aktief"</string> @@ -429,9 +432,13 @@ <string name="zen_modes_dialog_title" msgid="4159138230418567383">"Prioriteitmodusse"</string> <string name="zen_modes_dialog_done" msgid="6654130880256438950">"Klaar"</string> <string name="zen_modes_dialog_settings" msgid="2310248023728936697">"Instellings"</string> - <!-- no translation found for zen_mode_on (9085304934016242591) --> + <string name="zen_mode_on" msgid="9085304934016242591">"Aan"</string> + <string name="zen_mode_off" msgid="1736604456618147306">"Af"</string> + <!-- no translation found for zen_mode_set_up (7457957033034460064) --> <skip /> - <!-- no translation found for zen_mode_off (1736604456618147306) --> + <!-- no translation found for zen_mode_no_manual_invocation (1769975741344633672) --> + <skip /> + <!-- no translation found for zen_mode_active_modes (1625850411578488856) --> <skip /> <string name="zen_priority_introduction" msgid="3159291973383796646">"Jy sal nie deur geluide en vibrasies gepla word nie, behalwe deur wekkers, herinneringe, geleenthede en bellers wat jy spesifiseer. Jy sal steeds enigiets hoor wat jy kies om te speel, insluitend musiek, video\'s en speletjies."</string> <string name="zen_alarms_introduction" msgid="3987266042682300470">"Jy sal nie deur geluide en vibrasies gepla word nie, behalwe deur wekkers. Jy sal steeds enigiets hoor wat jy kies om te speel, insluitend musiek, video\'s en speletjies."</string> @@ -471,6 +478,8 @@ <string name="keyguard_indication_charging_time_slowly" msgid="301936949731705417">"<xliff:g id="PERCENTAGE">%2$s</xliff:g> • Laai tans stadig • Vol oor <xliff:g id="CHARGING_TIME_LEFT">%1$s</xliff:g>"</string> <string name="keyguard_indication_charging_time_dock" msgid="3149328898931741271">"<xliff:g id="PERCENTAGE">%2$s</xliff:g> • Laai tans • Vol oor <xliff:g id="CHARGING_TIME_LEFT">%1$s</xliff:g>"</string> <string name="accessibility_action_open_communal_hub" msgid="3081702792413787849">"Legstukke op sluitskerm"</string> + <!-- no translation found for accessibility_announcement_communal_widget_added (6911593106099328271) --> + <skip /> <string name="communal_tutorial_indicator_text" msgid="4503010353591430123">"Swiep links om die gemeenskaplike tutoriaal te begin"</string> <string name="cta_tile_button_to_open_widget_editor" msgid="3871562362382963878">"Pasmaak"</string> <string name="cta_tile_button_to_dismiss" msgid="3377597875997861754">"Maak toe"</string> @@ -499,8 +508,7 @@ <string name="accessibility_action_label_place_widget" msgid="1914197458644168978">"plaas gekose legstuk"</string> <string name="communal_widget_picker_title" msgid="1953369090475731663">"Sluitskermlegstukke"</string> <string name="communal_widget_picker_description" msgid="490515450110487871">"Enigiemand kan legstukke op jou sluitskerm sien, selfs al is jou tablet gesluit."</string> - <!-- no translation found for accessibility_action_label_unselect_widget (1041811747619468698) --> - <skip /> + <string name="accessibility_action_label_unselect_widget" msgid="1041811747619468698">"ontkies legstuk"</string> <string name="communal_widgets_disclaimer_title" msgid="1150954395585308868">"Sluitskermlegstukke"</string> <string name="communal_widgets_disclaimer_text" msgid="1423545475160506349">"Om ’n app met ’n legstuk oop te maak, sal jy moet verifieer dat dit jy is. Hou ook in gedagte dat enigeen dit kan bekyk, selfs wanneer jou tablet gesluit is. Sommige legstukke is moontlik nie vir jou sluitskerm bedoel nie en dit kan onveilig wees om dit hier by te voeg."</string> <string name="communal_widgets_disclaimer_button" msgid="4423059765740780753">"Het dit"</string> @@ -557,10 +565,8 @@ <string name="media_projection_action_text" msgid="3634906766918186440">"Begin nou"</string> <string name="empty_shade_text" msgid="8935967157319717412">"Geen kennisgewings nie"</string> <string name="no_unseen_notif_text" msgid="395512586119868682">"Geen nuwe kennisgewings nie"</string> - <!-- no translation found for adaptive_notification_edu_hun_title (7790738150177329960) --> - <skip /> - <!-- no translation found for adaptive_notification_edu_hun_text (7743367744129536610) --> - <skip /> + <string name="adaptive_notification_edu_hun_title" msgid="7790738150177329960">"Kennisgewingdemping is aan"</string> + <string name="adaptive_notification_edu_hun_text" msgid="7743367744129536610">"Jou toestelvolume en -waarskuwings word outomaties vir tot 2 minute lank verminder wanneer jy te veel kennisgewings op een slag kry."</string> <string name="go_to_adaptive_notification_settings" msgid="2423690125178298479">"Skakel af"</string> <string name="unlock_to_see_notif_text" msgid="7439033907167561227">"Ontsluit om ouer kennisgewings te sien"</string> <string name="quick_settings_disclosure_parental_controls" msgid="2114102871438223600">"Hierdie toestel word deur jou ouer bestuur"</string> @@ -1226,7 +1232,6 @@ <string name="accessibility_fingerprint_bouncer" msgid="7189102492498735519">"Stawing word vereis. Raak die vingerafdruksensor om te staaf."</string> <string name="ongoing_phone_call_content_description" msgid="5332334388483099947">"Oproep aan die gang"</string> <string name="mobile_data_settings_title" msgid="3955246641380064901">"Mobiele data"</string> - <string name="preference_summary_default_combination" msgid="8453246369903749670">"<xliff:g id="STATE">%1$s</xliff:g>/<xliff:g id="NETWORKMODE">%2$s</xliff:g>"</string> <string name="mobile_data_connection_active" msgid="944490013299018227">"Gekoppel"</string> <string name="mobile_data_temp_connection_active" msgid="4590222725908806824">"Tydelik gekoppel"</string> <string name="mobile_data_poor_connection" msgid="819617772268371434">"Swak verbinding"</string> @@ -1380,7 +1385,10 @@ <string name="touchpad_tutorial_done_button" msgid="176168488821755503">"Klaar"</string> <string name="touchpad_tutorial_gesture_done" msgid="4784438360736821255">"Uitstekende werk!"</string> <string name="touchpad_back_gesture_action_title" msgid="7199067250654332735">"Gaan terug"</string> - <string name="touchpad_back_gesture_guidance" msgid="4222430588599527272">"Swiep enige plek op die raakpaneel links of regs met drie vingers om terug te gaan."</string> + <!-- no translation found for touchpad_back_gesture_guidance (6263750214998421587) --> + <skip /> + <!-- no translation found for touchpad_back_gesture_finished (5353616006999726249) --> + <skip /> <string name="touchpad_back_gesture_animation_content_description" msgid="2646107450922379918">"Raakpaneel wat drie vingers wat regs en links beweeg wys"</string> <string name="touchpad_back_gesture_screen_animation_content_description" msgid="4036267494237748710">"Toestelskerm wat animasie vir teruggebaar wys"</string> <string name="keyboard_backlight_dialog_title" msgid="8273102932345564724">"Sleutelbordlig"</string> @@ -1388,28 +1396,16 @@ <string name="home_controls_dream_label" msgid="6567105701292324257">"Huiskontroles"</string> <string name="home_controls_dream_description" msgid="4644150952104035789">"Kry vinnig toegang tot jou huiskontroles as ’n sluimerskerm"</string> <string name="volume_undo_action" msgid="5815519725211877114">"Ontdoen"</string> - <!-- no translation found for back_edu_toast_content (4530314597378982956) --> - <skip /> - <!-- no translation found for home_edu_toast_content (3381071147871955415) --> - <skip /> - <!-- no translation found for overview_edu_toast_content (5797030644017804518) --> - <skip /> - <!-- no translation found for all_apps_edu_toast_content (8807496014667211562) --> - <skip /> - <!-- no translation found for back_edu_notification_title (5624780717751357278) --> - <skip /> - <!-- no translation found for back_edu_notification_content (2497557451540954068) --> - <skip /> - <!-- no translation found for home_edu_notification_title (6097902076909654045) --> - <skip /> - <!-- no translation found for home_edu_notification_content (6631697734535766588) --> - <skip /> - <!-- no translation found for overview_edu_notification_title (1265824157319562406) --> - <skip /> - <!-- no translation found for overview_edu_notification_content (3578204677648432500) --> - <skip /> - <!-- no translation found for all_apps_edu_notification_title (372262997265569063) --> - <skip /> - <!-- no translation found for all_apps_edu_notification_content (3255070575694025585) --> - <skip /> + <string name="back_edu_toast_content" msgid="4530314597378982956">"Swiep links of regs met drie vingers op die raakpaneel om terug te gaan"</string> + <string name="home_edu_toast_content" msgid="3381071147871955415">"Swiep op met drie vingers op die raakpaneel om terug na die tuisskerm te gaan"</string> + <string name="overview_edu_toast_content" msgid="5797030644017804518">"Swiep op en hou met drie vingers op die raakpaneel om onlangse apps te bekyk"</string> + <string name="all_apps_edu_toast_content" msgid="8807496014667211562">"Druk die handelingsleutel op jou sleutelbord om al jou apps te bekyk"</string> + <string name="back_edu_notification_title" msgid="5624780717751357278">"Gebruik jou raakpaneel om terug te gaan"</string> + <string name="back_edu_notification_content" msgid="2497557451540954068">"Swiep links of regs met drie vingers. Tik om meer gebare te leer."</string> + <string name="home_edu_notification_title" msgid="6097902076909654045">"Gebruik jou raakpaneel om na die tuisskerm toe te gaan"</string> + <string name="home_edu_notification_content" msgid="6631697734535766588">"Swiep op met drie vingers. Tik om meer gebare te leer."</string> + <string name="overview_edu_notification_title" msgid="1265824157319562406">"Gebruik jou raakpaneel om onlangse apps te bekyk"</string> + <string name="overview_edu_notification_content" msgid="3578204677648432500">"Swiep op en hou met drie vingers. Tik om meer gebare te leer."</string> + <string name="all_apps_edu_notification_title" msgid="372262997265569063">"Gebruik jou sleutelbord om alle apps te bekyk"</string> + <string name="all_apps_edu_notification_content" msgid="3255070575694025585">"Druk enige tyd die handelingsleutel. Tik om meer gebare te leer."</string> </resources> diff --git a/packages/SystemUI/res/values-af/tiles_states_strings.xml b/packages/SystemUI/res/values-af/tiles_states_strings.xml index d30156f30ad6..1b4781d24ebc 100644 --- a/packages/SystemUI/res/values-af/tiles_states_strings.xml +++ b/packages/SystemUI/res/values-af/tiles_states_strings.xml @@ -56,11 +56,6 @@ <item msgid="5376619709702103243">"Af"</item> <item msgid="4875147066469902392">"Aan"</item> </string-array> - <string-array name="tile_states_modes"> - <item msgid="7764936419245199023">"Onbeskikbaar"</item> - <item msgid="2004750556637773692">"Af"</item> - <item msgid="8968530753931637871">"Aan"</item> - </string-array> <string-array name="tile_states_flashlight"> <item msgid="3465257127433353857">"Onbeskikbaar"</item> <item msgid="5044688398303285224">"Af"</item> diff --git a/packages/SystemUI/res/values-am/strings.xml b/packages/SystemUI/res/values-am/strings.xml index f3edff723566..26e5c1e5d544 100644 --- a/packages/SystemUI/res/values-am/strings.xml +++ b/packages/SystemUI/res/values-am/strings.xml @@ -388,6 +388,9 @@ <string name="performance" msgid="6552785217174378320">"አፈጻጸም"</string> <string name="user_interface" msgid="3712869377953950887">"የተጠቃሚ በይነገፅ"</string> <string name="thermal" msgid="6758074791325414831">"ተርማል"</string> + <string name="custom" msgid="3337456985275158299">"ብጁ"</string> + <string name="custom_trace_settings_dialog_title" msgid="2608570500144830554">"የብጁ መከታተያ ቅንብሮች"</string> + <string name="restore_default" msgid="5259420807486239755">"ወደ ነባሪ መልስ"</string> <string name="quick_settings_onehanded_label" msgid="2416537930246274991">"የአንድ እጅ ሁነታ"</string> <string name="quick_settings_hearing_devices_label" msgid="7277170419679404129">"የመስሚያ መሣሪያዎች"</string> <string name="quick_settings_hearing_devices_connected" msgid="6519069502397037781">"ገቢር"</string> @@ -429,9 +432,13 @@ <string name="zen_modes_dialog_title" msgid="4159138230418567383">"ቅድሚያ ሁነታዎች"</string> <string name="zen_modes_dialog_done" msgid="6654130880256438950">"ተከናውኗል"</string> <string name="zen_modes_dialog_settings" msgid="2310248023728936697">"ቅንብሮች"</string> - <!-- no translation found for zen_mode_on (9085304934016242591) --> + <string name="zen_mode_on" msgid="9085304934016242591">"በርቷል"</string> + <string name="zen_mode_off" msgid="1736604456618147306">"ጠፍቷል"</string> + <!-- no translation found for zen_mode_set_up (7457957033034460064) --> <skip /> - <!-- no translation found for zen_mode_off (1736604456618147306) --> + <!-- no translation found for zen_mode_no_manual_invocation (1769975741344633672) --> + <skip /> + <!-- no translation found for zen_mode_active_modes (1625850411578488856) --> <skip /> <string name="zen_priority_introduction" msgid="3159291973383796646">"እርስዎ ከወሰንዋቸው ማንቂያዎች፣ አስታዋሾች፣ ክስተቶች እና ደዋዮች በስተቀር፣ በድምጾች እና ንዝረቶች አይረበሹም። ሙዚቃ፣ ቪዲዮዎች እና ጨዋታዎች ጨምሮ ለመጫወት የሚመርጡትን ማንኛውም ነገር አሁንም ይሰማሉ።"</string> <string name="zen_alarms_introduction" msgid="3987266042682300470">"ከማንቂያዎች በስተቀር፣ በድምጾች እና ንዝረቶች አይረበሹም። ሙዚቃ፣ ቪዲዮዎች እና ጨዋታዎች ጨምሮ ለመጫወት የሚመርጡትን ማንኛውም ነገር አሁንም ይሰማሉ።"</string> @@ -471,6 +478,8 @@ <string name="keyguard_indication_charging_time_slowly" msgid="301936949731705417">"<xliff:g id="PERCENTAGE">%2$s</xliff:g> • በዝግታ ኃይልን በመሙላት ላይ • በ<xliff:g id="CHARGING_TIME_LEFT">%1$s</xliff:g> ውስጥ ይሞላል"</string> <string name="keyguard_indication_charging_time_dock" msgid="3149328898931741271">"<xliff:g id="PERCENTAGE">%2$s</xliff:g> • ኃይል በመሙላት ላይ • በ<xliff:g id="CHARGING_TIME_LEFT">%1$s</xliff:g> ውስጥ ይሞላል"</string> <string name="accessibility_action_open_communal_hub" msgid="3081702792413787849">"ምግብሮች በማያ ገጽ ቁልፍ ላይ"</string> + <!-- no translation found for accessibility_announcement_communal_widget_added (6911593106099328271) --> + <skip /> <string name="communal_tutorial_indicator_text" msgid="4503010353591430123">"የጋራ አጋዥ ሥልጠናውን ለመጀመር ወደ ግራ ያንሸራትቱ።"</string> <string name="cta_tile_button_to_open_widget_editor" msgid="3871562362382963878">"አብጅ"</string> <string name="cta_tile_button_to_dismiss" msgid="3377597875997861754">"አሰናብት"</string> @@ -499,8 +508,7 @@ <string name="accessibility_action_label_place_widget" msgid="1914197458644168978">"በቦታ የተመረጠ ምግብር"</string> <string name="communal_widget_picker_title" msgid="1953369090475731663">"የማያ ገፅ ቁልፍ ምግብሮች"</string> <string name="communal_widget_picker_description" msgid="490515450110487871">"የእርስዎ ጡባዊ ቁልፍ ተቆልፎ ቢሆን እንኳን ማንኛውም ሰው በማያ ገፅ ቁልፍዎ ላይ ምግብሮችን ማየት ይችላል።"</string> - <!-- no translation found for accessibility_action_label_unselect_widget (1041811747619468698) --> - <skip /> + <string name="accessibility_action_label_unselect_widget" msgid="1041811747619468698">"ምግብር አትምረጥ"</string> <string name="communal_widgets_disclaimer_title" msgid="1150954395585308868">"የማያ ገፅ ቁልፍ ምግብሮች"</string> <string name="communal_widgets_disclaimer_text" msgid="1423545475160506349">"ምግብር በመጠቀም መተግበሪያ ለመክፈት እርስዎ መሆንዎን ማረጋገጥ አለብዎት። እንዲሁም የእርስዎ ጡባዊ በተቆለፈበት ጊዜ እንኳን ማንኛውም ሰው እነሱን ማየት እንደሚችል ከግምት ውስጥ ያስገቡ። አንዳንድ ምግብሮች ለማያ ገፅ ቁልፍዎ የታሰቡ ላይሆኑ ይችላሉ እና እዚህ ለማከል አስተማማኝ ላይሆኑ ይችላሉ።"</string> <string name="communal_widgets_disclaimer_button" msgid="4423059765740780753">"ገባኝ"</string> @@ -557,10 +565,8 @@ <string name="media_projection_action_text" msgid="3634906766918186440">"አሁን ጀምር"</string> <string name="empty_shade_text" msgid="8935967157319717412">"ምንም ማሳወቂያ የለም"</string> <string name="no_unseen_notif_text" msgid="395512586119868682">"ምንም አዲስ ማሳወቂያዎች የሉም"</string> - <!-- no translation found for adaptive_notification_edu_hun_title (7790738150177329960) --> - <skip /> - <!-- no translation found for adaptive_notification_edu_hun_text (7743367744129536610) --> - <skip /> + <string name="adaptive_notification_edu_hun_title" msgid="7790738150177329960">"የማሳወቂያ ረጋ ማለት በርቷል"</string> + <string name="adaptive_notification_edu_hun_text" msgid="7743367744129536610">"በአንድ ጊዜ ብዙ ማሳወቂያዎችን ሲያገኙ የመሣሪያዎ ድምፅ እና ማንቂያዎች እስከ 2 ደቂቃዎች ድረስ በራስ-ሰር ይቀንሳሉ።"</string> <string name="go_to_adaptive_notification_settings" msgid="2423690125178298479">"አጥፋ"</string> <string name="unlock_to_see_notif_text" msgid="7439033907167561227">"የቆዩ ማሳወቂያዎችን ለማየት ይክፈቱ"</string> <string name="quick_settings_disclosure_parental_controls" msgid="2114102871438223600">"ይህ መሣሪያ በእርስዎ ወላጅ የሚተዳደር ነው።"</string> @@ -1226,7 +1232,6 @@ <string name="accessibility_fingerprint_bouncer" msgid="7189102492498735519">"ማረጋገጥ ያስፈልጋል። ለማረጋገጥ የጣት አሻራ ዳሳሹን ይንኩ።"</string> <string name="ongoing_phone_call_content_description" msgid="5332334388483099947">"በመካሄድ ላይ የስልክ ጥሪ"</string> <string name="mobile_data_settings_title" msgid="3955246641380064901">"የተንቀሳቃሽ ስልክ ውሂብ"</string> - <string name="preference_summary_default_combination" msgid="8453246369903749670">"<xliff:g id="STATE">%1$s</xliff:g> / <xliff:g id="NETWORKMODE">%2$s</xliff:g>"</string> <string name="mobile_data_connection_active" msgid="944490013299018227">"ተገናኝቷል"</string> <string name="mobile_data_temp_connection_active" msgid="4590222725908806824">"በጊዜያዊነት ተገናኝቷል"</string> <string name="mobile_data_poor_connection" msgid="819617772268371434">"ደካማ ግንኙነት"</string> @@ -1380,7 +1385,10 @@ <string name="touchpad_tutorial_done_button" msgid="176168488821755503">"ተከናውኗል"</string> <string name="touchpad_tutorial_gesture_done" msgid="4784438360736821255">"ጥሩ ሠርተዋል!"</string> <string name="touchpad_back_gesture_action_title" msgid="7199067250654332735">"ወደኋላ ተመለስ"</string> - <string name="touchpad_back_gesture_guidance" msgid="4222430588599527272">"ወደኋላ ለመመለስ በመዳሰሻ ሰሌዳው ላይ በየትኛውም ቦታ ሦስት ጣቶችን በመጠቀም ወደግራ ወይም ወደቀኝ ያንሸራትቱ።"</string> + <!-- no translation found for touchpad_back_gesture_guidance (6263750214998421587) --> + <skip /> + <!-- no translation found for touchpad_back_gesture_finished (5353616006999726249) --> + <skip /> <string name="touchpad_back_gesture_animation_content_description" msgid="2646107450922379918">"ሦስት ጣቶች ወደቀኝ እና ግራ ሲንቀሳቀሱ የሚያሳይ የመዳሰሻ ሰሌዳ"</string> <string name="touchpad_back_gesture_screen_animation_content_description" msgid="4036267494237748710">"የኋላ ምልክት እነማ የሚያሳይ የመሣሪያ ማያ ገፅ"</string> <string name="keyboard_backlight_dialog_title" msgid="8273102932345564724">"የቁልፍ ሰሌዳ የጀርባ ብርሃን"</string> @@ -1388,28 +1396,16 @@ <string name="home_controls_dream_label" msgid="6567105701292324257">"የቤት ውስጥ ቁጥጥሮች"</string> <string name="home_controls_dream_description" msgid="4644150952104035789">"የቤት መቆጣጠሪያዎችዎን እንደ የገጸ ማያ አሳራፊ በፍጥነት ይድረሱባቸው"</string> <string name="volume_undo_action" msgid="5815519725211877114">"ቀልብስ"</string> - <!-- no translation found for back_edu_toast_content (4530314597378982956) --> - <skip /> - <!-- no translation found for home_edu_toast_content (3381071147871955415) --> - <skip /> - <!-- no translation found for overview_edu_toast_content (5797030644017804518) --> - <skip /> - <!-- no translation found for all_apps_edu_toast_content (8807496014667211562) --> - <skip /> - <!-- no translation found for back_edu_notification_title (5624780717751357278) --> - <skip /> - <!-- no translation found for back_edu_notification_content (2497557451540954068) --> - <skip /> - <!-- no translation found for home_edu_notification_title (6097902076909654045) --> - <skip /> - <!-- no translation found for home_edu_notification_content (6631697734535766588) --> - <skip /> - <!-- no translation found for overview_edu_notification_title (1265824157319562406) --> - <skip /> - <!-- no translation found for overview_edu_notification_content (3578204677648432500) --> - <skip /> - <!-- no translation found for all_apps_edu_notification_title (372262997265569063) --> - <skip /> - <!-- no translation found for all_apps_edu_notification_content (3255070575694025585) --> - <skip /> + <string name="back_edu_toast_content" msgid="4530314597378982956">"ለመመለስ የመዳሰሻ ሰሌዳው ላይ በሦስት ጣቶች ወደግራ ወይም ወደቀኝ ያንሸራትቱ"</string> + <string name="home_edu_toast_content" msgid="3381071147871955415">"ወደ መነሻ ለመሄድ የመዳሰሻ ሰሌዳው ላይ በሦስት ጣቶች ወደላይ ያንሸራትቱ"</string> + <string name="overview_edu_toast_content" msgid="5797030644017804518">"የቅርብ ጊዜ መተግበሪያዎችን ለማየት የመዳሰሻ ሰሌዳው ላይ በሦስት ጣቶች ወደላይ ያንሸራትቱ እና ይያዙ"</string> + <string name="all_apps_edu_toast_content" msgid="8807496014667211562">"ሁሉንም መተግበሪያዎችዎን ለማየት በቁልፍ ሰሌዳዎ ላይ ያለውን የተግባር ቁልፍ ይጫኑ"</string> + <string name="back_edu_notification_title" msgid="5624780717751357278">"ለመመለስ የመዳሰሻ ሰሌዳዎን ይጠቀሙ"</string> + <string name="back_edu_notification_content" msgid="2497557451540954068">"ሦስት ጣቶችን በመጠቀም ወደ ግራ ወይም ወደ ቀኝ ያንሸራትቱ። ምልክቶችን የበለጠ ለማወቅ መታ ያድርጉ።"</string> + <string name="home_edu_notification_title" msgid="6097902076909654045">"ወደ መነሻ ለመመለስ የመዳሰሻ ሰሌዳዎን ይጠቀሙ"</string> + <string name="home_edu_notification_content" msgid="6631697734535766588">"ሦስት ጣቶችን በመጠቀም ወደላይ ያንሸራትቱ። ምልክቶችን የበለጠ ለማወቅ መታ ያድርጉ።"</string> + <string name="overview_edu_notification_title" msgid="1265824157319562406">"የቅርብ ጊዜ መተግበሪያዎችን ለማየት የመዳሰሻ ሰሌዳዎን ይጠቀሙ"</string> + <string name="overview_edu_notification_content" msgid="3578204677648432500">"ሦስት ጣቶችን በመጠቀም ወደላይ ያንሸራትቱ እና ይያዙ። ምልክቶችን የበለጠ ለማወቅ መታ ያድርጉ።"</string> + <string name="all_apps_edu_notification_title" msgid="372262997265569063">"ሁሉንም መተግበሪያዎች ለማየት የቁልፍ ሰሌዳዎን ይጠቀሙ"</string> + <string name="all_apps_edu_notification_content" msgid="3255070575694025585">"በማንኛውም ጊዜ የተግባር ቁልፍን ይጫኑ። ምልክቶችን የበለጠ ለማወቅ መታ ያድርጉ።"</string> </resources> diff --git a/packages/SystemUI/res/values-am/tiles_states_strings.xml b/packages/SystemUI/res/values-am/tiles_states_strings.xml index 40cb02ed642c..a3c590c33a6f 100644 --- a/packages/SystemUI/res/values-am/tiles_states_strings.xml +++ b/packages/SystemUI/res/values-am/tiles_states_strings.xml @@ -56,11 +56,6 @@ <item msgid="5376619709702103243">"ጠፍቷል"</item> <item msgid="4875147066469902392">"በርቷል"</item> </string-array> - <string-array name="tile_states_modes"> - <item msgid="7764936419245199023">"አይገኝም"</item> - <item msgid="2004750556637773692">"ጠፍቷል"</item> - <item msgid="8968530753931637871">"በርቷል"</item> - </string-array> <string-array name="tile_states_flashlight"> <item msgid="3465257127433353857">"አይገኝም"</item> <item msgid="5044688398303285224">"ጠፍቷል"</item> diff --git a/packages/SystemUI/res/values-ar/strings.xml b/packages/SystemUI/res/values-ar/strings.xml index d5243f58d79f..3b65cd84d595 100644 --- a/packages/SystemUI/res/values-ar/strings.xml +++ b/packages/SystemUI/res/values-ar/strings.xml @@ -210,9 +210,9 @@ <string name="biometric_dialog_last_pattern_attempt_before_wipe_user" msgid="8400180746043407270">"عند إدخال نقش غير صحيح في المحاولة التالية، سيتم حذف هذا المستخدم."</string> <string name="biometric_dialog_last_pin_attempt_before_wipe_user" msgid="4159878829962411168">"عند إدخال رقم تعريف شخصي غير صحيح في المحاولة التالية، سيتم حذف هذا المستخدم."</string> <string name="biometric_dialog_last_password_attempt_before_wipe_user" msgid="4695682515465063885">"عند إدخال كلمة مرور غير صحيحة في المحاولة التالية، سيتم حذف هذا المستخدم."</string> - <string name="biometric_dialog_last_pattern_attempt_before_wipe_profile" msgid="6045224069529284686">"عند إدخال نقش غير صحيح في المحاولة التالية، سيتم حذف ملفك الشخصي للعمل وبياناته."</string> - <string name="biometric_dialog_last_pin_attempt_before_wipe_profile" msgid="545567685899091757">"عند إدخال رقم تعريف شخصي غير صحيح في المحاولة التالية، سيتم حذف ملفك الشخصي للعمل وبياناته."</string> - <string name="biometric_dialog_last_password_attempt_before_wipe_profile" msgid="8538032972389729253">"عند إدخال كلمة مرور غير صحيحة في المحاولة التالية، سيتم حذف ملفك الشخصي للعمل وبياناته."</string> + <string name="biometric_dialog_last_pattern_attempt_before_wipe_profile" msgid="6045224069529284686">"عند إدخال نقش غير صحيح في المحاولة التالية، سيتم حذف ملف العمل الخاص بك وبياناته."</string> + <string name="biometric_dialog_last_pin_attempt_before_wipe_profile" msgid="545567685899091757">"عند إدخال رقم تعريف شخصي غير صحيح في المحاولة التالية، سيتم حذف ملف العمل الخاص بك وبياناته."</string> + <string name="biometric_dialog_last_password_attempt_before_wipe_profile" msgid="8538032972389729253">"عند إدخال كلمة مرور غير صحيحة في المحاولة التالية، سيتم حذف ملف العمل الخاص بك وبياناته."</string> <string name="biometric_re_enroll_dialog_confirm" msgid="3049858021857801836">"إعداد"</string> <string name="biometric_re_enroll_dialog_cancel" msgid="93760939407091417">"لاحقًا"</string> <string name="biometric_re_enroll_notification_content" msgid="8685925877186288180">"هذا الإجراء مطلوب لتحسين مستوى الأمان والأداء."</string> @@ -222,11 +222,11 @@ <string name="fingerprint_re_enroll_dialog_content" msgid="4866561176695984879">"لإعادة إعداد ميزة \"فتح الجهاز ببصمة الإصبع\"، سيتم حذف صور بصمة الإصبع ونماذجها.\n\nبعد حذفها، عليك إعادة إعداد ميزة \"فتح الجهاز ببصمة الإصبع\" لتتمكن من استخدام بصمة الإصبع في فتح قفل الهاتف أو إثبات هويتك."</string> <string name="fingerprint_re_enroll_dialog_content_singular" msgid="3083663339787381218">"لإعادة إعداد ميزة \"فتح الجهاز ببصمة الإصبع\"، سيتم حذف صور بصمة الإصبع ونموذجها.\n\nبعد حذفها، عليك إعادة إعداد ميزة \"فتح الجهاز ببصمة الإصبع\" لتتمكن من استخدام بصمة الإصبع في فتح قفل الهاتف أو إثبات هويتك."</string> <string name="fingerprint_reenroll_failure_dialog_content" msgid="4733768492747300666">"تعذّر إعداد ميزة \"فتح الجهاز ببصمة الإصبع\". انتقِل إلى \"الإعدادات\" لإعادة المحاولة."</string> - <string name="face_re_enroll_notification_title" msgid="1850838867718410520">"إعادة إعداد ميزة \"فتح الجهاز بالتعرّف على الوجه\""</string> - <string name="face_re_enroll_notification_name" msgid="7384545252206120659">"فتح الجهاز بالتعرّف على الوجه"</string> - <string name="face_re_enroll_dialog_title" msgid="6392173708176069994">"إعداد ميزة \"فتح الجهاز بالتعرّف على الوجه\""</string> - <string name="face_re_enroll_dialog_content" msgid="7353502359464038511">"لإعادة إعداد ميزة \"فتح الجهاز بالتعرّف على الوجه\"، سيتم حذف نموذج الوجه الحالي.\n\nعليك إعادة إعداد الميزة لتتمكن من فتح قفل الهاتف باستخدام وجهك."</string> - <string name="face_reenroll_failure_dialog_content" msgid="7073947334397236935">"تعذّر إعداد ميزة \"فتح الجهاز بالتعرّف على الوجه\". انتقِل إلى \"الإعدادات\" لإعادة المحاولة."</string> + <string name="face_re_enroll_notification_title" msgid="1850838867718410520">"إعادة إعداد ميزة \"فتح الجهاز ببصمة الوجه\""</string> + <string name="face_re_enroll_notification_name" msgid="7384545252206120659">"فتح الجهاز ببصمة الوجه"</string> + <string name="face_re_enroll_dialog_title" msgid="6392173708176069994">"إعداد ميزة \"فتح الجهاز ببصمة الوجه\""</string> + <string name="face_re_enroll_dialog_content" msgid="7353502359464038511">"لإعادة إعداد ميزة \"فتح الجهاز ببصمة الوجه\"، سيتم حذف نموذج الوجه الحالي.\n\nعليك إعادة إعداد الميزة لتتمكن من فتح قفل الهاتف باستخدام وجهك."</string> + <string name="face_reenroll_failure_dialog_content" msgid="7073947334397236935">"تعذّر إعداد ميزة \"فتح الجهاز ببصمة الوجه\". انتقِل إلى \"الإعدادات\" لإعادة المحاولة."</string> <string name="fingerprint_dialog_touch_sensor" msgid="2817887108047658975">"المس أداة استشعار بصمة الإصبع"</string> <string name="fingerprint_dialog_authenticated_confirmation" msgid="1603899612957562862">"للمتابعة، اضغط على رمز فتح القفل."</string> <string name="fingerprint_dialog_use_fingerprint_instead" msgid="5542430577183894219">"يتعذّر التعرّف على الوجه. يمكنك استخدام بصمة إصبعك."</string> @@ -234,7 +234,7 @@ <skip /> <string name="keyguard_face_failed" msgid="2346762871330729634">"يتعذّر التعرّف على الوجه."</string> <string name="keyguard_suggest_fingerprint" msgid="8742015961962702960">"يمكنك استخدام بصمة إصبعك."</string> - <string name="keyguard_face_unlock_unavailable" msgid="1581949044193418736">"ميزة \"فتح الجهاز بالتعرف على الوجه\" غير متاحة."</string> + <string name="keyguard_face_unlock_unavailable" msgid="1581949044193418736">"ميزة \"فتح الجهاز ببصمة الوجه\" غير متاحة."</string> <string name="accessibility_bluetooth_connected" msgid="4745196874551115205">"تم توصيل البلوتوث."</string> <string name="accessibility_bluetooth_device_icon" msgid="9163840051642587982">"رمز الجهاز الذي يتضمّن بلوتوث"</string> <string name="accessibility_bluetooth_device_settings_gear" msgid="3314916468105272540">"انقر هنا لضبط إعدادات الجهاز."</string> @@ -388,6 +388,9 @@ <string name="performance" msgid="6552785217174378320">"الأداء"</string> <string name="user_interface" msgid="3712869377953950887">"واجهة المستخدم"</string> <string name="thermal" msgid="6758074791325414831">"الأداء الحراري"</string> + <string name="custom" msgid="3337456985275158299">"مخصّص"</string> + <string name="custom_trace_settings_dialog_title" msgid="2608570500144830554">"إعدادات التتبع المخصصة"</string> + <string name="restore_default" msgid="5259420807486239755">"استعادة الإعدادات التلقائية"</string> <string name="quick_settings_onehanded_label" msgid="2416537930246274991">"وضع \"التصفح بيد واحدة\""</string> <string name="quick_settings_hearing_devices_label" msgid="7277170419679404129">"سماعات الأذن الطبية"</string> <string name="quick_settings_hearing_devices_connected" msgid="6519069502397037781">"متّصلة حاليًا"</string> @@ -429,9 +432,13 @@ <string name="zen_modes_dialog_title" msgid="4159138230418567383">"الأوضاع ذات الأولوية"</string> <string name="zen_modes_dialog_done" msgid="6654130880256438950">"تم"</string> <string name="zen_modes_dialog_settings" msgid="2310248023728936697">"الإعدادات"</string> - <!-- no translation found for zen_mode_on (9085304934016242591) --> + <string name="zen_mode_on" msgid="9085304934016242591">"مفعَّل"</string> + <string name="zen_mode_off" msgid="1736604456618147306">"غير مفعَّل"</string> + <!-- no translation found for zen_mode_set_up (7457957033034460064) --> <skip /> - <!-- no translation found for zen_mode_off (1736604456618147306) --> + <!-- no translation found for zen_mode_no_manual_invocation (1769975741344633672) --> + <skip /> + <!-- no translation found for zen_mode_active_modes (1625850411578488856) --> <skip /> <string name="zen_priority_introduction" msgid="3159291973383796646">"لن يتم إزعاجك بالأصوات والاهتزاز، باستثناء المُنبِّهات والتذكيرات والأحداث والمتصلين الذين تحددهم. وسيظل بإمكانك سماع أي عناصر أخرى تختار تشغيلها، بما في ذلك الموسيقى والفيديوهات والألعاب."</string> <string name="zen_alarms_introduction" msgid="3987266042682300470">"لن يتم إزعاجك بالأصوات والاهتزاز، باستثناء المُنبِّهات. وسيظل بإمكانك سماع أي عناصر أخرى تختار تشغيلها، بما في ذلك الموسيقى والفيديوهات والألعاب."</string> @@ -443,14 +450,14 @@ <string name="keyguard_unlock" msgid="8031975796351361601">"التمرير إلى الأعلى لفتح القفل"</string> <string name="keyguard_unlock_press" msgid="9140109453735019209">"اضغط على رمز فتح القفل لفتح قفل الشاشة."</string> <string name="keyguard_face_successful_unlock_swipe" msgid="6180997591385846073">"تم فتح قفل جهازك عند تقريبه من وجهك. مرِّر سريعًا للأعلى لفتح الجهاز."</string> - <string name="keyguard_face_successful_unlock_press" msgid="25520941264602588">"تم فتح القفل بالتعرّف على وجهك. لفتح الجهاز، اضغط على رمز فتح القفل."</string> + <string name="keyguard_face_successful_unlock_press" msgid="25520941264602588">"تم فتح القفل ببصمة وجهك. لفتح الجهاز، اضغط على رمز فتح القفل."</string> <string name="keyguard_face_successful_unlock_press_alt_1" msgid="5715461103913071474">"تم فتح قفل جهازك عند تقريبه من وجهك. اضغط لفتح الجهاز."</string> <string name="keyguard_face_successful_unlock_press_alt_2" msgid="8310787946357120406">"تم التعرّف على الوجه. اضغط لفتح الجهاز."</string> <string name="keyguard_face_successful_unlock_press_alt_3" msgid="7219030481255573962">"تم التعرّف على الوجه. اضغط على رمز فتح القفل لفتح الجهاز."</string> <string name="keyguard_face_successful_unlock" msgid="4203999851465708287">"تم فتح قفل جهازك عند تقريبه من وجهك."</string> <string name="keyguard_face_successful_unlock_alt1" msgid="5853906076353839628">"تم التعرّف على الوجه."</string> <string name="keyguard_retry" msgid="886802522584053523">"مرِّر سريعًا للأعلى لإعادة المحاولة."</string> - <string name="accesssibility_keyguard_retry" msgid="8880238862712870676">"مرِّر سريعًا للأعلى لاستخدام \"فتح الجهاز بالتعرف على الوجه\""</string> + <string name="accesssibility_keyguard_retry" msgid="8880238862712870676">"مرِّر سريعًا للأعلى لاستخدام ميزة \"فتح الجهاز ببصمة الوجه\""</string> <string name="require_unlock_for_nfc" msgid="1305686454823018831">"افتح قفل الشاشة لاستخدام تقنية NFC"</string> <string name="do_disclosure_generic" msgid="4896482821974707167">"هذا الجهاز يخص مؤسستك."</string> <string name="do_disclosure_with_name" msgid="2091641464065004091">"هذا الجهاز يخص <xliff:g id="ORGANIZATION_NAME">%s</xliff:g>."</string> @@ -471,6 +478,8 @@ <string name="keyguard_indication_charging_time_slowly" msgid="301936949731705417">"<xliff:g id="PERCENTAGE">%2$s</xliff:g> • جارٍ الشحن ببطء • ستمتلئ البطارية خلال <xliff:g id="CHARGING_TIME_LEFT">%1$s</xliff:g>"</string> <string name="keyguard_indication_charging_time_dock" msgid="3149328898931741271">"<xliff:g id="PERCENTAGE">%2$s</xliff:g> • جارٍ الشحن • ستمتلئ البطارية خلال <xliff:g id="CHARGING_TIME_LEFT">%1$s</xliff:g>"</string> <string name="accessibility_action_open_communal_hub" msgid="3081702792413787849">"التطبيقات المصغّرة على شاشة القفل"</string> + <!-- no translation found for accessibility_announcement_communal_widget_added (6911593106099328271) --> + <skip /> <string name="communal_tutorial_indicator_text" msgid="4503010353591430123">"مرِّر سريعًا لليمين لبدء الدليل التوجيهي العام."</string> <string name="cta_tile_button_to_open_widget_editor" msgid="3871562362382963878">"تخصيص"</string> <string name="cta_tile_button_to_dismiss" msgid="3377597875997861754">"إغلاق"</string> @@ -499,8 +508,7 @@ <string name="accessibility_action_label_place_widget" msgid="1914197458644168978">"إضافة التطبيق المصغّر المحدَّد"</string> <string name="communal_widget_picker_title" msgid="1953369090475731663">"التطبيقات المصغّرة المصمَّمة لشاشة القفل"</string> <string name="communal_widget_picker_description" msgid="490515450110487871">"يمكن للجميع رؤية التطبيقات المصغّرة على شاشة القفل، حتى في حال قفل الجهاز اللوحي."</string> - <!-- no translation found for accessibility_action_label_unselect_widget (1041811747619468698) --> - <skip /> + <string name="accessibility_action_label_unselect_widget" msgid="1041811747619468698">"إلغاء اختيار التطبيق المصغّر"</string> <string name="communal_widgets_disclaimer_title" msgid="1150954395585308868">"التطبيقات المصغّرة المصمَّمة لشاشة القفل"</string> <string name="communal_widgets_disclaimer_text" msgid="1423545475160506349">"لفتح تطبيق باستخدام تطبيق مصغَّر، عليك إثبات هويتك. يُرجى ملاحظة أنّ أي شخص يمكنه الاطّلاع محتوى التطبيقات المصغَّرة، حتى وإن كان جهازك اللوحي مُقفلاً. بعض التطبيقات المصغّرة قد لا تكون مُصمَّمة لإضافتها إلى شاشة القفل، وقد يكون هذا الإجراء غير آمن."</string> <string name="communal_widgets_disclaimer_button" msgid="4423059765740780753">"حسنًا"</string> @@ -557,10 +565,8 @@ <string name="media_projection_action_text" msgid="3634906766918186440">"البدء الآن"</string> <string name="empty_shade_text" msgid="8935967157319717412">"ما مِن إشعارات"</string> <string name="no_unseen_notif_text" msgid="395512586119868682">"ما مِن إشعارات جديدة"</string> - <!-- no translation found for adaptive_notification_edu_hun_title (7790738150177329960) --> - <skip /> - <!-- no translation found for adaptive_notification_edu_hun_text (7743367744129536610) --> - <skip /> + <string name="adaptive_notification_edu_hun_title" msgid="7790738150177329960">"ميزة \"تخفيض الإشعارات الصوتية والاهتزاز\" مُفعَّلة"</string> + <string name="adaptive_notification_edu_hun_text" msgid="7743367744129536610">"يتم تلقائيًا خفض مستوى صوت جهازك والتنبيهات لمدة تصل إلى دقيقتين عند تلقّي إشعارات كثيرة في آنٍ واحد."</string> <string name="go_to_adaptive_notification_settings" msgid="2423690125178298479">"إيقاف"</string> <string name="unlock_to_see_notif_text" msgid="7439033907167561227">"افتَح قفل الشاشة لعرض الإشعارات الأقدم."</string> <string name="quick_settings_disclosure_parental_controls" msgid="2114102871438223600">"يتولّى أحد الوالدين إدارة هذا الجهاز."</string> @@ -574,7 +580,7 @@ <string name="quick_settings_disclosure_management_vpns" msgid="929181757984262902">"ينتمي هذا الجهاز إلى مؤسستك، ويتّصل بالإنترنت من خلال خدمات الشبكة الافتراضية الخاصة (VPN)."</string> <string name="quick_settings_disclosure_named_management_vpns" msgid="3312645578322079185">"ينتمي هذا الجهاز إلى <xliff:g id="ORGANIZATION_NAME">%1$s</xliff:g>، ويتّصل بالإنترنت من خلال خدمات الشبكة الافتراضية الخاصة (VPN)."</string> <string name="quick_settings_disclosure_managed_profile_monitoring" msgid="1423899084754272514">"يمكن لمؤسستك مراقبة حركة بيانات الشبكة في ملف العمل"</string> - <string name="quick_settings_disclosure_named_managed_profile_monitoring" msgid="8321469176706219860">"يمكن لـ <xliff:g id="ORGANIZATION_NAME">%1$s</xliff:g> مراقبة حركة بيانات الشبكة في ملفك الشخصي للعمل"</string> + <string name="quick_settings_disclosure_named_managed_profile_monitoring" msgid="8321469176706219860">"يمكن لـ <xliff:g id="ORGANIZATION_NAME">%1$s</xliff:g> مراقبة حركة بيانات الشبكة في ملف العمل الخاص بك"</string> <string name="quick_settings_disclosure_managed_profile_network_activity" msgid="2636594621387832827">"تكون أنشطة شبكة ملف العمل مرئية لمشرف تكنولوجيا المعلومات."</string> <string name="quick_settings_disclosure_monitoring" msgid="8548019955631378680">"قد تكون الشبكة خاضعة للمراقبة"</string> <string name="quick_settings_disclosure_vpns" msgid="3586175303518266301">"هذا الجهاز متّصل بالإنترنت من خلال خدمات الشبكات الافتراضية الخاصة (VPN)."</string> @@ -592,10 +598,10 @@ <string name="monitoring_financed_description_named_management" msgid="6108439201399938668">"قد تتمكّن مؤسسة <xliff:g id="ORGANIZATION_NAME_0">%1$s</xliff:g> من الوصول إلى البيانات المرتبطة بهذا الجهاز وإدارة التطبيقات وتغيير إعدادات الجهاز.\n\nإذا كان لديك أسئلة، يُرجى التواصل مع <xliff:g id="ORGANIZATION_NAME_1">%2$s</xliff:g>."</string> <string name="monitoring_description_management" msgid="4308879039175729014">"هذا الجهاز يخص مؤسستك.\n\nيمكن لمشرف تكنولوجيا المعلومات في مؤسستك تتبّع وإدارة الإعدادات والتطبيقات والبيانات المرتبطة بجهازك ومعلومات الموقع الجغرافي للجهاز وعمليات الدخول إلى نظام المؤسسة.\n\nللحصول على المزيد من المعلومات، يمكنك التواصل مع مشرف تكنولوجيا المعلومات."</string> <string name="monitoring_description_management_ca_certificate" msgid="7785013130658110130">"ثبّتت مؤسستك مرجعًا مصدّقًا على هذا الجهاز. قد تتم مراقبة حركة بيانات شبكتك الآمنة أو تعديلها."</string> - <string name="monitoring_description_managed_profile_ca_certificate" msgid="7904323416598435647">"ثبّتت مؤسستك مرجعًا مصدّقًا في ملفك الشخصي للعمل. قد تتم مراقبة حركة بيانات شبكتك الآمنة أو تعديلها."</string> + <string name="monitoring_description_managed_profile_ca_certificate" msgid="7904323416598435647">"ثبّتت مؤسستك مرجعًا مصدّقًا في ملف العمل الخاص بك. قد تتم مراقبة حركة بيانات شبكتك الآمنة أو تعديلها."</string> <string name="monitoring_description_ca_certificate" msgid="448923057059097497">"تم تثبيت مرجع مصدّق على هذا الجهاز. قد تتم مراقبة حركة بيانات شبكتك الآمنة أو تعديلها."</string> <string name="monitoring_description_management_network_logging" msgid="216983105036994771">"شغَّل المشرف ميزة تسجيل بيانات الشبكة، والتي يتم من خلالها مراقبة حركة البيانات على جهازك."</string> - <string name="monitoring_description_managed_profile_network_logging" msgid="6932303843097006037">"شغَّل المشرف ميزة تسجيل بيانات الشبكة، والتي يتم من خلالها مراقبة حركة البيانات في ملفك الشخصي للعمل ولكن لا تتم مراقبتها في ملفك الشخصي."</string> + <string name="monitoring_description_managed_profile_network_logging" msgid="6932303843097006037">"شغَّل المشرف ميزة تسجيل بيانات الشبكة، والتي يتم من خلالها مراقبة حركة البيانات في ملف العمل الخاص بك ولكن لا تتم مراقبتها في ملفك الشخصي."</string> <string name="monitoring_description_named_vpn" msgid="8220190039787149671">"هذا الجهاز متّصل بالإنترنت من خلال \"<xliff:g id="VPN_APP">%1$s</xliff:g>\". ويمكن لمقدِّم شبكة VPN الاطّلاع على أنشطة الشبكة، بما في ذلك الرسائل الإلكترونية وبيانات التصفّح."</string> <string name="monitoring_description_managed_device_named_vpn" msgid="7693648349547785255">"هذا الجهاز متّصل بالإنترنت من خلال \"<xliff:g id="VPN_APP">%1$s</xliff:g>\". تجدر الإشارة إلى أنّ أنشطة الشبكة، بما في ذلك الرسائل الإلكترونية وبيانات التصفُّح، مرئية لمشرف تكنولوجيا المعلومات في مؤسستك."</string> <string name="monitoring_description_two_named_vpns" msgid="6726394451199620634">"هذا الجهاز متّصل بالإنترنت من خلال <xliff:g id="VPN_APP_0">%1$s</xliff:g> و<xliff:g id="VPN_APP_1">%2$s</xliff:g>. يمكن لمشرف تكنولوجيا المعلومات رؤية أنشطة الشبكة، بما في ذلك الرسائل الإلكترونية وبيانات التصفُّح."</string> @@ -687,7 +693,7 @@ <string name="show_demo_mode" msgid="3677956462273059726">"عرض الوضع التجريبي"</string> <string name="status_bar_ethernet" msgid="5690979758988647484">"إيثرنت"</string> <string name="status_bar_alarm" msgid="87160847643623352">"المنبّه"</string> - <string name="wallet_title" msgid="5369767670735827105">"محفظة"</string> + <string name="wallet_title" msgid="5369767670735827105">"محفظة Google"</string> <string name="wallet_empty_state_label" msgid="7776761245237530394">"يمكنك إعداد طريقة دفع لإجراء عمليات شراء بسرعة وأمان أكبر باستخدام هاتفك."</string> <string name="wallet_app_button_label" msgid="7123784239111190992">"عرض الكل"</string> <string name="wallet_secondary_label_no_card" msgid="8488069304491125713">"انقر لفتح قفل الجهاز"</string> @@ -1226,7 +1232,6 @@ <string name="accessibility_fingerprint_bouncer" msgid="7189102492498735519">"المصادقة مطلوبة. المس مستشعر بصمات الإصبع للمصادقة."</string> <string name="ongoing_phone_call_content_description" msgid="5332334388483099947">"مكالمة هاتفية جارية"</string> <string name="mobile_data_settings_title" msgid="3955246641380064901">"بيانات الجوّال"</string> - <string name="preference_summary_default_combination" msgid="8453246369903749670">"<xliff:g id="STATE">%1$s</xliff:g> / <xliff:g id="NETWORKMODE">%2$s</xliff:g>"</string> <string name="mobile_data_connection_active" msgid="944490013299018227">"متصلة بالإنترنت"</string> <string name="mobile_data_temp_connection_active" msgid="4590222725908806824">"متصلة مؤقتًا"</string> <string name="mobile_data_poor_connection" msgid="819617772268371434">"الاتصال ضعيف"</string> @@ -1380,7 +1385,10 @@ <string name="touchpad_tutorial_done_button" msgid="176168488821755503">"تم"</string> <string name="touchpad_tutorial_gesture_done" msgid="4784438360736821255">"أحسنت."</string> <string name="touchpad_back_gesture_action_title" msgid="7199067250654332735">"رجوع"</string> - <string name="touchpad_back_gesture_guidance" msgid="4222430588599527272">"للرجوع، مرِّر سريعًا لليسار أو لليمين باستخدام ثلاثة أصابع في أي مكان على لوحة اللمس."</string> + <!-- no translation found for touchpad_back_gesture_guidance (6263750214998421587) --> + <skip /> + <!-- no translation found for touchpad_back_gesture_finished (5353616006999726249) --> + <skip /> <string name="touchpad_back_gesture_animation_content_description" msgid="2646107450922379918">"لوحة لمس تعرض ثلاثة أصابع تتحرك يمينًا ويسارًا"</string> <string name="touchpad_back_gesture_screen_animation_content_description" msgid="4036267494237748710">"شاشة جهاز تعرض صورة متحركة لإيماءة الرجوع"</string> <string name="keyboard_backlight_dialog_title" msgid="8273102932345564724">"الإضاءة الخلفية للوحة المفاتيح"</string> @@ -1388,28 +1396,16 @@ <string name="home_controls_dream_label" msgid="6567105701292324257">"إدارة المنزل آليًّا"</string> <string name="home_controls_dream_description" msgid="4644150952104035789">"يمكنك إدارة المنزل آليًّا بشكل سريع من شاشة الاستراحة"</string> <string name="volume_undo_action" msgid="5815519725211877114">"تراجع"</string> - <!-- no translation found for back_edu_toast_content (4530314597378982956) --> - <skip /> - <!-- no translation found for home_edu_toast_content (3381071147871955415) --> - <skip /> - <!-- no translation found for overview_edu_toast_content (5797030644017804518) --> - <skip /> - <!-- no translation found for all_apps_edu_toast_content (8807496014667211562) --> - <skip /> - <!-- no translation found for back_edu_notification_title (5624780717751357278) --> - <skip /> - <!-- no translation found for back_edu_notification_content (2497557451540954068) --> - <skip /> - <!-- no translation found for home_edu_notification_title (6097902076909654045) --> - <skip /> - <!-- no translation found for home_edu_notification_content (6631697734535766588) --> - <skip /> - <!-- no translation found for overview_edu_notification_title (1265824157319562406) --> - <skip /> - <!-- no translation found for overview_edu_notification_content (3578204677648432500) --> - <skip /> - <!-- no translation found for all_apps_edu_notification_title (372262997265569063) --> - <skip /> - <!-- no translation found for all_apps_edu_notification_content (3255070575694025585) --> - <skip /> + <string name="back_edu_toast_content" msgid="4530314597378982956">"للرجوع، مرِّر سريعًا لليمين أو لليسار على لوحة اللمس باستخدام 3 أصابع"</string> + <string name="home_edu_toast_content" msgid="3381071147871955415">"للانتقال إلى الشاشة الرئيسية، مرِّر سريعًا للأعلى على لوحة اللمس باستخدام 3 أصابع"</string> + <string name="overview_edu_toast_content" msgid="5797030644017804518">"لعرض التطبيقات المستخدَمة مؤخرًا، مرِّر سريعًا للأعلى مع استمرار الضغط على لوحة اللمس باستخدام 3 أصابع"</string> + <string name="all_apps_edu_toast_content" msgid="8807496014667211562">"لعرض جميع التطبيقات، اضغط على مفتاح الإجراء في لوحة المفاتيح"</string> + <string name="back_edu_notification_title" msgid="5624780717751357278">"استخدِم لوحة اللمس للرجوع"</string> + <string name="back_edu_notification_content" msgid="2497557451540954068">"مرِّر سريعًا لليمين أو لليسار باستخدام 3 أصابع. انقر للتعرّف على المزيد من الإيماءات."</string> + <string name="home_edu_notification_title" msgid="6097902076909654045">"استخدِم لوحة اللمس للانتقال إلى الشاشة الرئيسية"</string> + <string name="home_edu_notification_content" msgid="6631697734535766588">"مرِّر سريعًا للأعلى باستخدام 3 أصابع. انقر للتعرّف على المزيد من الإيماءات."</string> + <string name="overview_edu_notification_title" msgid="1265824157319562406">"استخدِم لوحة اللمس لعرض التطبيقات المستخدَمة مؤخرًا"</string> + <string name="overview_edu_notification_content" msgid="3578204677648432500">"مرِّر سريعًا للأعلى مع استمرار الضغط باستخدام 3 أصابع. انقر للتعرّف على المزيد من الإيماءات."</string> + <string name="all_apps_edu_notification_title" msgid="372262997265569063">"استخدِم لوحة المفاتيح لعرض جميع التطبيقات"</string> + <string name="all_apps_edu_notification_content" msgid="3255070575694025585">"اضغط على مفتاح الإجراء في أي وقت. انقر للتعرّف على المزيد من الإيماءات."</string> </resources> diff --git a/packages/SystemUI/res/values-ar/tiles_states_strings.xml b/packages/SystemUI/res/values-ar/tiles_states_strings.xml index acb38feed48d..a89650aa6e19 100644 --- a/packages/SystemUI/res/values-ar/tiles_states_strings.xml +++ b/packages/SystemUI/res/values-ar/tiles_states_strings.xml @@ -56,11 +56,6 @@ <item msgid="5376619709702103243">"الميزة غير مفعّلة"</item> <item msgid="4875147066469902392">"الميزة مفعّلة"</item> </string-array> - <string-array name="tile_states_modes"> - <item msgid="7764936419245199023">"غير متوفّرة"</item> - <item msgid="2004750556637773692">"غير مفعَّلة"</item> - <item msgid="8968530753931637871">"مفعَّلة"</item> - </string-array> <string-array name="tile_states_flashlight"> <item msgid="3465257127433353857">"الميزة غير متاحة"</item> <item msgid="5044688398303285224">"الميزة غير مفعّلة"</item> diff --git a/packages/SystemUI/res/values-as/strings.xml b/packages/SystemUI/res/values-as/strings.xml index b1fa417c070b..576e8ad2b252 100644 --- a/packages/SystemUI/res/values-as/strings.xml +++ b/packages/SystemUI/res/values-as/strings.xml @@ -388,6 +388,9 @@ <string name="performance" msgid="6552785217174378320">"পাৰদৰ্শিতা"</string> <string name="user_interface" msgid="3712869377953950887">"ব্যৱহাৰকাৰীৰ ইণ্টাৰফে’চ"</string> <string name="thermal" msgid="6758074791325414831">"থাৰ্মেল"</string> + <string name="custom" msgid="3337456985275158299">"কাষ্টম"</string> + <string name="custom_trace_settings_dialog_title" msgid="2608570500144830554">"কাষ্টম ট্ৰে’চৰ ছেটিং"</string> + <string name="restore_default" msgid="5259420807486239755">"ডিফ’ল্ট পুনঃস্থাপন কৰক"</string> <string name="quick_settings_onehanded_label" msgid="2416537930246274991">"এখন হাতেৰে ব্যৱহাৰ কৰা ম’ড"</string> <string name="quick_settings_hearing_devices_label" msgid="7277170419679404129">"শুনাৰ ডিভাইচ"</string> <string name="quick_settings_hearing_devices_connected" msgid="6519069502397037781">"সক্ৰিয় হৈ আছে"</string> @@ -429,10 +432,11 @@ <string name="zen_modes_dialog_title" msgid="4159138230418567383">"অগ্ৰাধিকাৰপ্ৰাপ্ত ম’ডসমূহ"</string> <string name="zen_modes_dialog_done" msgid="6654130880256438950">"কৰা হ’ল"</string> <string name="zen_modes_dialog_settings" msgid="2310248023728936697">"ছেটিং"</string> - <!-- no translation found for zen_mode_on (9085304934016242591) --> - <skip /> - <!-- no translation found for zen_mode_off (1736604456618147306) --> - <skip /> + <string name="zen_mode_on" msgid="9085304934016242591">"অন আছে"</string> + <string name="zen_mode_off" msgid="1736604456618147306">"অফ আছে"</string> + <string name="zen_mode_set_up" msgid="7457957033034460064">"ছেট আপ কৰক"</string> + <string name="zen_mode_no_manual_invocation" msgid="1769975741344633672">"ছেটিঙত পৰিচালনা কৰক"</string> + <string name="zen_mode_active_modes" msgid="1625850411578488856">"{count,plural, =0{কোনো সক্ৰিয় ম’ড নাই}=1{{mode} সক্ৰিয় আছে}one{# টা ম’ড সক্ৰিয় আছে}other{# টা ম’ড সক্ৰিয় আছে}}"</string> <string name="zen_priority_introduction" msgid="3159291973383796646">"আপুনি নিৰ্দিষ্ট কৰা এলাৰ্ম, ৰিমাইণ্ডাৰ, ইভেন্ট আৰু কল কৰোঁতাৰ বাহিৰে আন কোনো শব্দৰ পৰা আপুনি অসুবিধা নাপাব। কিন্তু, সংগীত, ভিডিঅ\' আৰু খেলসমূহকে ধৰি আপুনি প্লে কৰিব খোজা যিকোনো বস্তু তথাপি শুনিব পাৰিব।"</string> <string name="zen_alarms_introduction" msgid="3987266042682300470">"আপুনি নিৰ্দিষ্ট কৰা এলাৰ্মৰ বাহিৰে আন কোনো ধ্বনি আৰু কম্পনৰ পৰা আপুনি অসুবিধা নাপাব। কিন্তু, সংগীত, ভিডিঅ\' আৰু খেলসমূহকে ধৰি আপুনি প্লে কৰিব খোজা যিকোনো বস্তু তথাপি শুনিব পাৰিব।"</string> <string name="zen_priority_customize_button" msgid="4119213187257195047">"কাষ্টমাইজ কৰক"</string> @@ -471,6 +475,8 @@ <string name="keyguard_indication_charging_time_slowly" msgid="301936949731705417">"<xliff:g id="PERCENTAGE">%2$s</xliff:g> • লাহে লাহে চাৰ্জ হৈ আছে • <xliff:g id="CHARGING_TIME_LEFT">%1$s</xliff:g>ত সম্পূৰ্ণ হ’ব"</string> <string name="keyguard_indication_charging_time_dock" msgid="3149328898931741271">"<xliff:g id="PERCENTAGE">%2$s</xliff:g> • চাৰ্জ হৈ আছে • <xliff:g id="CHARGING_TIME_LEFT">%1$s</xliff:g>ত সম্পূৰ্ণ হ’ব"</string> <string name="accessibility_action_open_communal_hub" msgid="3081702792413787849">"লক স্ক্ৰীনত ৱিজেট"</string> + <!-- no translation found for accessibility_announcement_communal_widget_added (6911593106099328271) --> + <skip /> <string name="communal_tutorial_indicator_text" msgid="4503010353591430123">"সম্প্ৰদায় সম্পৰ্কীয় নিৰ্দেশনা আৰম্ভ কৰিবলৈ বাওঁফালে ছোৱাইপ কৰক"</string> <string name="cta_tile_button_to_open_widget_editor" msgid="3871562362382963878">"কাষ্টমাইজ কৰক"</string> <string name="cta_tile_button_to_dismiss" msgid="3377597875997861754">"অগ্ৰাহ্য কৰক"</string> @@ -499,8 +505,7 @@ <string name="accessibility_action_label_place_widget" msgid="1914197458644168978">"বাছনি কৰা ৱিজেটটো ৰাখক"</string> <string name="communal_widget_picker_title" msgid="1953369090475731663">"লক স্ক্ৰীনৰ ৱিজেট"</string> <string name="communal_widget_picker_description" msgid="490515450110487871">"আপোনাৰ টেবলেটটো লক কৰি ৰাখিলেও যিকোনো লোকে আপোনাৰ লক স্ক্ৰীনত ৱিজেট চাব পাৰে।"</string> - <!-- no translation found for accessibility_action_label_unselect_widget (1041811747619468698) --> - <skip /> + <string name="accessibility_action_label_unselect_widget" msgid="1041811747619468698">"ৱিজেট বাছনিৰ পৰা আঁতৰাওক"</string> <string name="communal_widgets_disclaimer_title" msgid="1150954395585308868">"লক স্ক্ৰীন ৱিজেট"</string> <string name="communal_widgets_disclaimer_text" msgid="1423545475160506349">"এটা ৱিজেট ব্যৱহাৰ কৰি কোনো এপ্ খুলিবলৈ, এয়া আপুনিয়েই বুলি সত্যাপন পৰীক্ষা কৰিব লাগিব। লগতে, মনত ৰাখিব যে যিকোনো লোকেই সেইবোৰ চাব পাৰে, আনকি আপোনাৰ টেবলেটটো লক হৈ থাকিলেও। কিছুমান ৱিজেট হয়তো আপোনাৰ লক স্ক্ৰীনৰ বাবে কৰা হোৱা নাই আৰু ইয়াত যোগ কৰাটো অসুৰক্ষিত হ’ব পাৰে।"</string> <string name="communal_widgets_disclaimer_button" msgid="4423059765740780753">"বুজি পালোঁ"</string> @@ -557,10 +562,8 @@ <string name="media_projection_action_text" msgid="3634906766918186440">"এতিয়াই আৰম্ভ কৰক"</string> <string name="empty_shade_text" msgid="8935967157319717412">"কোনো জাননী নাই"</string> <string name="no_unseen_notif_text" msgid="395512586119868682">"কোনো নতুন জাননী নাই"</string> - <!-- no translation found for adaptive_notification_edu_hun_title (7790738150177329960) --> - <skip /> - <!-- no translation found for adaptive_notification_edu_hun_text (7743367744129536610) --> - <skip /> + <string name="adaptive_notification_edu_hun_title" msgid="7790738150177329960">"জাননী কুলডাউন কৰাটো অন আছে"</string> + <string name="adaptive_notification_edu_hun_text" msgid="7743367744129536610">"আপুনি একেলগে বহুতো জাননী পালে আপোনাৰ ডিভাইচটোৰ ভলিউম আৰু সতৰ্কবাৰ্তা স্বয়ংক্ৰিয়ভাৱে ২ মিনিটলৈকে কমোৱা হয়।"</string> <string name="go_to_adaptive_notification_settings" msgid="2423690125178298479">"অফ কৰক"</string> <string name="unlock_to_see_notif_text" msgid="7439033907167561227">"পুৰণি জাননী চবলৈ আনলক কৰক"</string> <string name="quick_settings_disclosure_parental_controls" msgid="2114102871438223600">"এই ডিভাইচটো আপোনাৰ অভিভাৱকে পৰিচালনা কৰে"</string> @@ -1226,7 +1229,6 @@ <string name="accessibility_fingerprint_bouncer" msgid="7189102492498735519">"বিশ্বাসযোগ্যতা প্ৰমাণীকৰণৰ আৱশ্যক। বিশ্বাসযোগ্যতা প্ৰমাণীকৰণ কৰিবলৈ ফিংগাৰপ্ৰিণ্ট ছেন্সৰটো স্পৰ্শ কৰক।"</string> <string name="ongoing_phone_call_content_description" msgid="5332334388483099947">"চলি থকা ফ’ন কল"</string> <string name="mobile_data_settings_title" msgid="3955246641380064901">"ম’বাইল ডেটা"</string> - <string name="preference_summary_default_combination" msgid="8453246369903749670">"<xliff:g id="STATE">%1$s</xliff:g> / <xliff:g id="NETWORKMODE">%2$s</xliff:g>"</string> <string name="mobile_data_connection_active" msgid="944490013299018227">"সংযোজিত হৈ আছে"</string> <string name="mobile_data_temp_connection_active" msgid="4590222725908806824">"অস্থায়ীভাৱে সংযোগ কৰা হৈছে"</string> <string name="mobile_data_poor_connection" msgid="819617772268371434">"বেয়া সংযোগ"</string> @@ -1380,7 +1382,10 @@ <string name="touchpad_tutorial_done_button" msgid="176168488821755503">"হ’ল"</string> <string name="touchpad_tutorial_gesture_done" msgid="4784438360736821255">"বঢ়িয়া!"</string> <string name="touchpad_back_gesture_action_title" msgid="7199067250654332735">"উভতি যাওক"</string> - <string name="touchpad_back_gesture_guidance" msgid="4222430588599527272">"উভতি যাবলৈ, টাচ্চপেডৰ যিকোনো স্থানত তিনিটা আঙুলি ব্যৱহাৰ কৰি বাওঁ বা সোঁফালে ছোৱাইপ কৰক।"</string> + <!-- no translation found for touchpad_back_gesture_guidance (6263750214998421587) --> + <skip /> + <!-- no translation found for touchpad_back_gesture_finished (5353616006999726249) --> + <skip /> <string name="touchpad_back_gesture_animation_content_description" msgid="2646107450922379918">"তিনিটা আঙুলি সোঁ আৰু বাওঁফালে লৰচৰ কৰা দেখুওৱা টাচ্চপেড"</string> <string name="touchpad_back_gesture_screen_animation_content_description" msgid="4036267494237748710">"পিছফালৰ নিৰ্দেশৰ এনিমেশ্বন দেখুওৱা ডিভাইচ স্ক্ৰীন"</string> <string name="keyboard_backlight_dialog_title" msgid="8273102932345564724">"কীব’ৰ্ডৰ বেকলাইট"</string> @@ -1388,28 +1393,16 @@ <string name="home_controls_dream_label" msgid="6567105701292324257">"ঘৰৰ সা-সৰঞ্জামৰ নিয়ন্ত্ৰণ"</string> <string name="home_controls_dream_description" msgid="4644150952104035789">"স্ক্ৰীনছেভাৰ হিচাপে ক্ষিপ্ৰতাৰে ঘৰৰ সা-সৰঞ্জামৰ নিয়ন্ত্ৰণ এক্সেছ কৰক"</string> <string name="volume_undo_action" msgid="5815519725211877114">"আনডু কৰক"</string> - <!-- no translation found for back_edu_toast_content (4530314597378982956) --> - <skip /> - <!-- no translation found for home_edu_toast_content (3381071147871955415) --> - <skip /> - <!-- no translation found for overview_edu_toast_content (5797030644017804518) --> - <skip /> - <!-- no translation found for all_apps_edu_toast_content (8807496014667211562) --> - <skip /> - <!-- no translation found for back_edu_notification_title (5624780717751357278) --> - <skip /> - <!-- no translation found for back_edu_notification_content (2497557451540954068) --> - <skip /> - <!-- no translation found for home_edu_notification_title (6097902076909654045) --> - <skip /> - <!-- no translation found for home_edu_notification_content (6631697734535766588) --> - <skip /> - <!-- no translation found for overview_edu_notification_title (1265824157319562406) --> - <skip /> - <!-- no translation found for overview_edu_notification_content (3578204677648432500) --> - <skip /> - <!-- no translation found for all_apps_edu_notification_title (372262997265569063) --> - <skip /> - <!-- no translation found for all_apps_edu_notification_content (3255070575694025585) --> - <skip /> + <string name="back_edu_toast_content" msgid="4530314597378982956">"উভতি যাবলৈ টাচ্চপেডখনত তিনিটা আঙুলিৰে বাওঁ বা সোঁফালে ছোৱাইপ কৰক"</string> + <string name="home_edu_toast_content" msgid="3381071147871955415">"গৃহপৃষ্ঠালৈ যাওক, টাচ্চপেডত তিনিটা আঙুলিৰে ওপৰলৈ ছোৱাইপ কৰক"</string> + <string name="overview_edu_toast_content" msgid="5797030644017804518">"শেহতীয়া এপ্সমূহ চাবলৈ টাচ্চপেডখনত তিনিটা আঙুলিৰে ওপৰলৈ ছোৱাইপ কৰি ধৰি ৰাখক"</string> + <string name="all_apps_edu_toast_content" msgid="8807496014667211562">"আপোনাৰ আটাইবোৰ এপ্ চাবলৈ আপোনাৰ কীব’ৰ্ডৰ কাৰ্য কীটোত টিপক"</string> + <string name="back_edu_notification_title" msgid="5624780717751357278">"উভতি যাবলৈ আপোনাৰ টাচ্চপেড ব্যৱহাৰ কৰক"</string> + <string name="back_edu_notification_content" msgid="2497557451540954068">"তিনিটা আঙুলি ব্যৱহাৰ কৰি বাওঁফাললৈ বা সোঁফাললৈ ছোৱাইপ কৰক। অধিক নিৰ্দেশ শিকিবলৈ টিপক।"</string> + <string name="home_edu_notification_title" msgid="6097902076909654045">"গৃহপৃষ্ঠালৈ যাবলৈ আপোনাৰ টাচ্চপেড ব্যৱহাৰ কৰক"</string> + <string name="home_edu_notification_content" msgid="6631697734535766588">"তিনিটা আঙুলি ব্যৱহাৰ কৰি ওপৰলৈ ছোৱাইপ কৰক। অধিক নিৰ্দেশ শিকিবলৈ টিপক।"</string> + <string name="overview_edu_notification_title" msgid="1265824157319562406">"শেহতীয়া এপ্সমূহ চাবলৈ আপোনাৰ টাচ্চপেড ব্যৱহাৰ কৰক"</string> + <string name="overview_edu_notification_content" msgid="3578204677648432500">"তিনিটা আঙুলি ব্যৱহাৰ কৰি ওপৰলৈ ছোৱাইপ কৰি ধৰি ৰাখক। অধিক নিৰ্দেশ শিকিবলৈ টিপক।"</string> + <string name="all_apps_edu_notification_title" msgid="372262997265569063">"আটাইবোৰ এপ্ চাবলৈ আপোনাৰ কীব’ৰ্ড ব্যৱহাৰ কৰক"</string> + <string name="all_apps_edu_notification_content" msgid="3255070575694025585">"যিকোনো সময়তে কাৰ্য কীটোত টিপক। অধিক নিৰ্দেশ শিকিবলৈ টিপক।"</string> </resources> diff --git a/packages/SystemUI/res/values-as/tiles_states_strings.xml b/packages/SystemUI/res/values-as/tiles_states_strings.xml index fdd1f103674d..e978fe279a6e 100644 --- a/packages/SystemUI/res/values-as/tiles_states_strings.xml +++ b/packages/SystemUI/res/values-as/tiles_states_strings.xml @@ -56,11 +56,6 @@ <item msgid="5376619709702103243">"অফ আছে"</item> <item msgid="4875147066469902392">"অন কৰা আছে"</item> </string-array> - <string-array name="tile_states_modes"> - <item msgid="7764936419245199023">"উপলব্ধ নহয়"</item> - <item msgid="2004750556637773692">"অফ আছে"</item> - <item msgid="8968530753931637871">"অন আছে"</item> - </string-array> <string-array name="tile_states_flashlight"> <item msgid="3465257127433353857">"উপলব্ধ নহয়"</item> <item msgid="5044688398303285224">"অফ আছে"</item> diff --git a/packages/SystemUI/res/values-az/strings.xml b/packages/SystemUI/res/values-az/strings.xml index d748edc0dcbc..d6abf079a2c0 100644 --- a/packages/SystemUI/res/values-az/strings.xml +++ b/packages/SystemUI/res/values-az/strings.xml @@ -388,6 +388,9 @@ <string name="performance" msgid="6552785217174378320">"Performans"</string> <string name="user_interface" msgid="3712869377953950887">"İstifadəçi interfeysi"</string> <string name="thermal" msgid="6758074791325414831">"Termal"</string> + <string name="custom" msgid="3337456985275158299">"Fərdi"</string> + <string name="custom_trace_settings_dialog_title" msgid="2608570500144830554">"Fərdi fəaliyyət izi ayarları"</string> + <string name="restore_default" msgid="5259420807486239755">"Defoltu bərpa edin"</string> <string name="quick_settings_onehanded_label" msgid="2416537930246274991">"Birəlli rejim"</string> <string name="quick_settings_hearing_devices_label" msgid="7277170419679404129">"Eşitmə cihazları"</string> <string name="quick_settings_hearing_devices_connected" msgid="6519069502397037781">"Aktiv"</string> @@ -429,9 +432,13 @@ <string name="zen_modes_dialog_title" msgid="4159138230418567383">"Prioritet rejimləri"</string> <string name="zen_modes_dialog_done" msgid="6654130880256438950">"Hazırdır"</string> <string name="zen_modes_dialog_settings" msgid="2310248023728936697">"Ayarlar"</string> - <!-- no translation found for zen_mode_on (9085304934016242591) --> + <string name="zen_mode_on" msgid="9085304934016242591">"Aktiv"</string> + <string name="zen_mode_off" msgid="1736604456618147306">"Deaktiv"</string> + <!-- no translation found for zen_mode_set_up (7457957033034460064) --> <skip /> - <!-- no translation found for zen_mode_off (1736604456618147306) --> + <!-- no translation found for zen_mode_no_manual_invocation (1769975741344633672) --> + <skip /> + <!-- no translation found for zen_mode_active_modes (1625850411578488856) --> <skip /> <string name="zen_priority_introduction" msgid="3159291973383796646">"Seçdiyiniz siqnal, xatırladıcı, tədbir və zənglər istisna olmaqla səslər və vibrasiyalar Sizi narahat etməyəcək. Musiqi, video və oyunlar da daxil olmaqla oxutmaq istədiyiniz hər şeyi eşidəcəksiniz."</string> <string name="zen_alarms_introduction" msgid="3987266042682300470">"Siqnallar istisna olmaqla səslər və vibrasiyalar Sizi narahat etməyəcək. Musiqi, video və oyunlar da daxil olmaqla oxutmaq istədiyiniz hər şeyi eşidəcəksiniz."</string> @@ -471,6 +478,8 @@ <string name="keyguard_indication_charging_time_slowly" msgid="301936949731705417">"<xliff:g id="PERCENTAGE">%2$s</xliff:g> • Asta şarj edilir • <xliff:g id="CHARGING_TIME_LEFT">%1$s</xliff:g> sonra dolacaq"</string> <string name="keyguard_indication_charging_time_dock" msgid="3149328898931741271">"<xliff:g id="PERCENTAGE">%2$s</xliff:g> • Şarj edilir • <xliff:g id="CHARGING_TIME_LEFT">%1$s</xliff:g> sonra dolacaq"</string> <string name="accessibility_action_open_communal_hub" msgid="3081702792413787849">"Kilid ekranındakı vidcetlər"</string> + <!-- no translation found for accessibility_announcement_communal_widget_added (6911593106099328271) --> + <skip /> <string name="communal_tutorial_indicator_text" msgid="4503010353591430123">"İcma təlimatını başlatmaq üçün sola sürüşdürün"</string> <string name="cta_tile_button_to_open_widget_editor" msgid="3871562362382963878">"Fərdiləşdirin"</string> <string name="cta_tile_button_to_dismiss" msgid="3377597875997861754">"Bağlayın"</string> @@ -499,8 +508,7 @@ <string name="accessibility_action_label_place_widget" msgid="1914197458644168978">"seçilmiş vidceti yerləşdirin"</string> <string name="communal_widget_picker_title" msgid="1953369090475731663">"Kilid ekranı vidcetləri"</string> <string name="communal_widget_picker_description" msgid="490515450110487871">"Planşet kilidli olsa belə, hər kəs kilid ekranınızdakı vidcetlərə baxa bilər."</string> - <!-- no translation found for accessibility_action_label_unselect_widget (1041811747619468698) --> - <skip /> + <string name="accessibility_action_label_unselect_widget" msgid="1041811747619468698">"vidcet seçimini silin"</string> <string name="communal_widgets_disclaimer_title" msgid="1150954395585308868">"Kilid ekranı vidcetləri"</string> <string name="communal_widgets_disclaimer_text" msgid="1423545475160506349">"Vidcetdən istifadə edərək tətbiqi açmaq üçün kimliyi doğrulamalısınız. Planşet kilidli olsa da, hər kəs vidcetlərə baxa bilər. Bəzi vidcetlər kilid ekranı üçün nəzərdə tutulmayıb və bura əlavə etmək təhlükəli ola bilər."</string> <string name="communal_widgets_disclaimer_button" msgid="4423059765740780753">"Anladım"</string> @@ -557,10 +565,8 @@ <string name="media_projection_action_text" msgid="3634906766918186440">"İndi başlayın"</string> <string name="empty_shade_text" msgid="8935967157319717412">"Heç bir bildiriş yoxdur"</string> <string name="no_unseen_notif_text" msgid="395512586119868682">"Yeni bildiriş yoxdur"</string> - <!-- no translation found for adaptive_notification_edu_hun_title (7790738150177329960) --> - <skip /> - <!-- no translation found for adaptive_notification_edu_hun_text (7743367744129536610) --> - <skip /> + <string name="adaptive_notification_edu_hun_title" msgid="7790738150177329960">"Bildiriş gözləmə müddəti yanılıdır"</string> + <string name="adaptive_notification_edu_hun_text" msgid="7743367744129536610">"Eyni anda çox bildiriş aldıqda cihazın səs və xəbərdarlıqları avtomatik 2 dəqiqəyə qədər azalır."</string> <string name="go_to_adaptive_notification_settings" msgid="2423690125178298479">"Deaktiv edin"</string> <string name="unlock_to_see_notif_text" msgid="7439033907167561227">"Köhnə bildirişləri görmək üçün kilidi açın"</string> <string name="quick_settings_disclosure_parental_controls" msgid="2114102871438223600">"Bu cihaz valideyniniz tərəfindən idarə olunur"</string> @@ -1226,7 +1232,6 @@ <string name="accessibility_fingerprint_bouncer" msgid="7189102492498735519">"Doğrulanma tələb olunur. Doğrulamaq üçün barmaq izi sensoruna toxunun."</string> <string name="ongoing_phone_call_content_description" msgid="5332334388483099947">"Davam edən zəng"</string> <string name="mobile_data_settings_title" msgid="3955246641380064901">"Mobil data"</string> - <string name="preference_summary_default_combination" msgid="8453246369903749670">"<xliff:g id="STATE">%1$s</xliff:g> / <xliff:g id="NETWORKMODE">%2$s</xliff:g>"</string> <string name="mobile_data_connection_active" msgid="944490013299018227">"Qoşulub"</string> <string name="mobile_data_temp_connection_active" msgid="4590222725908806824">"Müvəqqəti qoşulub"</string> <string name="mobile_data_poor_connection" msgid="819617772268371434">"Zəif bağlantı"</string> @@ -1380,7 +1385,10 @@ <string name="touchpad_tutorial_done_button" msgid="176168488821755503">"Hazırdır"</string> <string name="touchpad_tutorial_gesture_done" msgid="4784438360736821255">"Əla!"</string> <string name="touchpad_back_gesture_action_title" msgid="7199067250654332735">"Geri qayıdın"</string> - <string name="touchpad_back_gesture_guidance" msgid="4222430588599527272">"Geri qayıtmaq üçün taçpedin istənilən yerində üç barmaqla sola və ya sağa çəkin."</string> + <!-- no translation found for touchpad_back_gesture_guidance (6263750214998421587) --> + <skip /> + <!-- no translation found for touchpad_back_gesture_finished (5353616006999726249) --> + <skip /> <string name="touchpad_back_gesture_animation_content_description" msgid="2646107450922379918">"Üç barmağın sağa və sola hərəkət etdiyini göstərən taçped"</string> <string name="touchpad_back_gesture_screen_animation_content_description" msgid="4036267494237748710">"Geri jesti üçün animasiya göstərən cihaz ekranı"</string> <string name="keyboard_backlight_dialog_title" msgid="8273102932345564724">"Klaviatura işığı"</string> @@ -1388,28 +1396,16 @@ <string name="home_controls_dream_label" msgid="6567105701292324257">"Ev nizamlayıcıları"</string> <string name="home_controls_dream_description" msgid="4644150952104035789">"Ekran qoruyucu kimi ev nizamlayıcılarına tez giriş"</string> <string name="volume_undo_action" msgid="5815519725211877114">"Geri qaytarın"</string> - <!-- no translation found for back_edu_toast_content (4530314597378982956) --> - <skip /> - <!-- no translation found for home_edu_toast_content (3381071147871955415) --> - <skip /> - <!-- no translation found for overview_edu_toast_content (5797030644017804518) --> - <skip /> - <!-- no translation found for all_apps_edu_toast_content (8807496014667211562) --> - <skip /> - <!-- no translation found for back_edu_notification_title (5624780717751357278) --> - <skip /> - <!-- no translation found for back_edu_notification_content (2497557451540954068) --> - <skip /> - <!-- no translation found for home_edu_notification_title (6097902076909654045) --> - <skip /> - <!-- no translation found for home_edu_notification_content (6631697734535766588) --> - <skip /> - <!-- no translation found for overview_edu_notification_title (1265824157319562406) --> - <skip /> - <!-- no translation found for overview_edu_notification_content (3578204677648432500) --> - <skip /> - <!-- no translation found for all_apps_edu_notification_title (372262997265569063) --> - <skip /> - <!-- no translation found for all_apps_edu_notification_content (3255070575694025585) --> - <skip /> + <string name="back_edu_toast_content" msgid="4530314597378982956">"Geri qayıtmaq üçün taçpeddə üç barmağınızla sola və ya sağa çəkin"</string> + <string name="home_edu_toast_content" msgid="3381071147871955415">"Ana səhifəyə keçmək üçün taçpeddə üç barmağınızla yuxarı çəkin"</string> + <string name="overview_edu_toast_content" msgid="5797030644017804518">"Son tətbiqlərə baxmaq üçün taçpeddə üç barmağınızla yuxarı çəkib saxlayın"</string> + <string name="all_apps_edu_toast_content" msgid="8807496014667211562">"Bütün tətbiqlərə baxmaq üçün klaviaturada fəaliyyət açarını basın"</string> + <string name="back_edu_notification_title" msgid="5624780717751357278">"Geri qayıtmaq üçün taçped istifadə edin"</string> + <string name="back_edu_notification_content" msgid="2497557451540954068">"Üç barmaqla sola və ya sağa çəkin. Daha çox jest öyrənmək üçün toxunun."</string> + <string name="home_edu_notification_title" msgid="6097902076909654045">"Ana səhifəyə keçmək üçün taçped istifadə edin"</string> + <string name="home_edu_notification_content" msgid="6631697734535766588">"Üç barmaqla yuxarı çəkin. Daha çox jest öyrənmək üçün toxunun."</string> + <string name="overview_edu_notification_title" msgid="1265824157319562406">"Son tətbiqlərə baxmaq üçün taçped istifadə edin"</string> + <string name="overview_edu_notification_content" msgid="3578204677648432500">"Üç barmaq ilə yuxarı çəkib saxlayın. Daha çox jest öyrənmək üçün toxunun."</string> + <string name="all_apps_edu_notification_title" msgid="372262997265569063">"Bütün tətbiqlərə baxmaq üçün klaviatura istifadə edin"</string> + <string name="all_apps_edu_notification_content" msgid="3255070575694025585">"İstənilən vaxt fəaliyyət açarını basın. Daha çox jest öyrənmək üçün toxunun."</string> </resources> diff --git a/packages/SystemUI/res/values-az/tiles_states_strings.xml b/packages/SystemUI/res/values-az/tiles_states_strings.xml index 678c94ddf57f..c24f4029e415 100644 --- a/packages/SystemUI/res/values-az/tiles_states_strings.xml +++ b/packages/SystemUI/res/values-az/tiles_states_strings.xml @@ -56,11 +56,6 @@ <item msgid="5376619709702103243">"Deaktiv"</item> <item msgid="4875147066469902392">"Aktiv"</item> </string-array> - <string-array name="tile_states_modes"> - <item msgid="7764936419245199023">"Əlçatan deyil"</item> - <item msgid="2004750556637773692">"Deaktiv"</item> - <item msgid="8968530753931637871">"Aktiv"</item> - </string-array> <string-array name="tile_states_flashlight"> <item msgid="3465257127433353857">"Əlçatan deyil"</item> <item msgid="5044688398303285224">"Deaktiv"</item> diff --git a/packages/SystemUI/res/values-b+sr+Latn/strings.xml b/packages/SystemUI/res/values-b+sr+Latn/strings.xml index 28144a62ff19..307dcc097aec 100644 --- a/packages/SystemUI/res/values-b+sr+Latn/strings.xml +++ b/packages/SystemUI/res/values-b+sr+Latn/strings.xml @@ -141,7 +141,7 @@ <string name="cast_to_other_device_stop_dialog_title" msgid="7836517190930357326">"Želite da zaustavite prebacivanje?"</string> <string name="cast_to_other_device_stop_dialog_message_entire_screen_with_device" msgid="1474703115926205251">"Trenutno prebacujete ceo ekran na: <xliff:g id="DEVICE_NAME">%1$s</xliff:g>"</string> <string name="cast_to_other_device_stop_dialog_message_entire_screen" msgid="8419219169553867625">"Trenutno prebacujete ceo ekran na uređaj u blizini"</string> - <string name="cast_to_other_device_stop_dialog_message_specific_app_with_device" msgid="2715934698604085519">"<xliff:g id="APP_BEING_SHARED_NAME">%1$s</xliff:g> se trenutno prebacuje na: <xliff:g id="DEVICE_NAME">%2$s</xliff:g>"</string> + <string name="cast_to_other_device_stop_dialog_message_specific_app_with_device" msgid="2715934698604085519">"<xliff:g id="APP_BEING_SHARED_NAME">%1$s</xliff:g> trenutno prebacujete na: <xliff:g id="DEVICE_NAME">%2$s</xliff:g>"</string> <string name="cast_to_other_device_stop_dialog_message_specific_app" msgid="8616103075630934513">"<xliff:g id="APP_BEING_SHARED_NAME">%1$s</xliff:g> se trenutno prebacuje na uređaj u blizini"</string> <string name="cast_to_other_device_stop_dialog_message_generic_with_device" msgid="9213582497852420203">"Trenutno prebacujete na: <xliff:g id="DEVICE_NAME">%1$s</xliff:g>"</string> <string name="cast_to_other_device_stop_dialog_message_generic" msgid="4100272100480415076">"Trenutno prebacujete na uređaj u blizini"</string> @@ -388,6 +388,9 @@ <string name="performance" msgid="6552785217174378320">"Performanse"</string> <string name="user_interface" msgid="3712869377953950887">"Korisnički interfejs"</string> <string name="thermal" msgid="6758074791325414831">"Termalna kamera"</string> + <string name="custom" msgid="3337456985275158299">"Prilagođeno"</string> + <string name="custom_trace_settings_dialog_title" msgid="2608570500144830554">"Podešavanja prilagođenog praćenja"</string> + <string name="restore_default" msgid="5259420807486239755">"Vrati podrazumevano"</string> <string name="quick_settings_onehanded_label" msgid="2416537930246274991">"Režim jednom rukom"</string> <string name="quick_settings_hearing_devices_label" msgid="7277170419679404129">"Slušni aparati"</string> <string name="quick_settings_hearing_devices_connected" msgid="6519069502397037781">"Aktivno"</string> @@ -429,9 +432,13 @@ <string name="zen_modes_dialog_title" msgid="4159138230418567383">"Prioritetni režimi"</string> <string name="zen_modes_dialog_done" msgid="6654130880256438950">"Gotovo"</string> <string name="zen_modes_dialog_settings" msgid="2310248023728936697">"Podešavanja"</string> - <!-- no translation found for zen_mode_on (9085304934016242591) --> + <string name="zen_mode_on" msgid="9085304934016242591">"Uključeno"</string> + <string name="zen_mode_off" msgid="1736604456618147306">"Isključeno"</string> + <!-- no translation found for zen_mode_set_up (7457957033034460064) --> <skip /> - <!-- no translation found for zen_mode_off (1736604456618147306) --> + <!-- no translation found for zen_mode_no_manual_invocation (1769975741344633672) --> + <skip /> + <!-- no translation found for zen_mode_active_modes (1625850411578488856) --> <skip /> <string name="zen_priority_introduction" msgid="3159291973383796646">"Neće vas uznemiravati zvukovi i vibracije osim za alarme, podsetnike, događaje i pozivaoce koje navedete. I dalje ćete čuti sve što odaberete da pustite, uključujući muziku, video snimke i igre."</string> <string name="zen_alarms_introduction" msgid="3987266042682300470">"Neće vas uznemiravati zvukovi i vibracije osim za alarme. I dalje ćete čuti sve što odaberete da pustite, uključujući muziku, video snimke i igre."</string> @@ -471,6 +478,8 @@ <string name="keyguard_indication_charging_time_slowly" msgid="301936949731705417">"<xliff:g id="PERCENTAGE">%2$s</xliff:g> • Sporo se puni • <xliff:g id="CHARGING_TIME_LEFT">%1$s</xliff:g> do kraja punjenja"</string> <string name="keyguard_indication_charging_time_dock" msgid="3149328898931741271">"<xliff:g id="PERCENTAGE">%2$s</xliff:g> • Puni se • <xliff:g id="CHARGING_TIME_LEFT">%1$s</xliff:g> do kraja punjenja"</string> <string name="accessibility_action_open_communal_hub" msgid="3081702792413787849">"Vidžeti na zaključanom ekranu"</string> + <!-- no translation found for accessibility_announcement_communal_widget_added (6911593106099328271) --> + <skip /> <string name="communal_tutorial_indicator_text" msgid="4503010353591430123">"Prevucite ulevo da biste započeli zajednički vodič"</string> <string name="cta_tile_button_to_open_widget_editor" msgid="3871562362382963878">"Prilagodite"</string> <string name="cta_tile_button_to_dismiss" msgid="3377597875997861754">"Odbaci"</string> @@ -498,9 +507,8 @@ <string name="accessibility_action_label_remove_widget" msgid="3373779447448758070">"uklonite vidžet"</string> <string name="accessibility_action_label_place_widget" msgid="1914197458644168978">"postavite izabrani vidžet"</string> <string name="communal_widget_picker_title" msgid="1953369090475731663">"Vidžeti za zaključani ekran"</string> - <string name="communal_widget_picker_description" msgid="490515450110487871">"Svi mogu da vide vedžete na zaključanom ekranu, čak i kada je tablet zaključan."</string> - <!-- no translation found for accessibility_action_label_unselect_widget (1041811747619468698) --> - <skip /> + <string name="communal_widget_picker_description" msgid="490515450110487871">"Svi mogu da vide vidžete na zaključanom ekranu, čak i kada je tablet zaključan."</string> + <string name="accessibility_action_label_unselect_widget" msgid="1041811747619468698">"poništi izbor vidžeta"</string> <string name="communal_widgets_disclaimer_title" msgid="1150954395585308868">"Vidžeti za zaključani ekran"</string> <string name="communal_widgets_disclaimer_text" msgid="1423545475160506349">"Da biste otvorili aplikaciju koja koristi vidžet, treba da potvrdite da ste to vi. Imajte u vidu da svako može da ga vidi, čak i kada je tablet zaključan. Neki vidžeti možda nisu namenjeni za zaključani ekran i možda nije bezbedno da ih tamo dodate."</string> <string name="communal_widgets_disclaimer_button" msgid="4423059765740780753">"Važi"</string> @@ -557,10 +565,8 @@ <string name="media_projection_action_text" msgid="3634906766918186440">"Započni"</string> <string name="empty_shade_text" msgid="8935967157319717412">"Nema obaveštenja"</string> <string name="no_unseen_notif_text" msgid="395512586119868682">"Nema novih obaveštenja"</string> - <!-- no translation found for adaptive_notification_edu_hun_title (7790738150177329960) --> - <skip /> - <!-- no translation found for adaptive_notification_edu_hun_text (7743367744129536610) --> - <skip /> + <string name="adaptive_notification_edu_hun_title" msgid="7790738150177329960">"Utišavanje obaveštenja je uključeno"</string> + <string name="adaptive_notification_edu_hun_text" msgid="7743367744129536610">"Zvuk i broj upozorenja na uređaju se automatski smanjuju na 2 minuta kada dobijete previše obaveštenja."</string> <string name="go_to_adaptive_notification_settings" msgid="2423690125178298479">"Isključi"</string> <string name="unlock_to_see_notif_text" msgid="7439033907167561227">"Otključajte za starija obaveštenja"</string> <string name="quick_settings_disclosure_parental_controls" msgid="2114102871438223600">"Ovim uređajem upravlja roditelj"</string> @@ -1226,7 +1232,6 @@ <string name="accessibility_fingerprint_bouncer" msgid="7189102492498735519">"Potrebna je potvrda identiteta. Dodirnite senzor za otisak prsta da biste potvrdili identitet."</string> <string name="ongoing_phone_call_content_description" msgid="5332334388483099947">"Aktuelni telefonski poziv"</string> <string name="mobile_data_settings_title" msgid="3955246641380064901">"Mobilni podaci"</string> - <string name="preference_summary_default_combination" msgid="8453246369903749670">"<xliff:g id="STATE">%1$s</xliff:g>/<xliff:g id="NETWORKMODE">%2$s</xliff:g>"</string> <string name="mobile_data_connection_active" msgid="944490013299018227">"Povezano"</string> <string name="mobile_data_temp_connection_active" msgid="4590222725908806824">"Privremeno povezano"</string> <string name="mobile_data_poor_connection" msgid="819617772268371434">"Veza je loša"</string> @@ -1380,7 +1385,10 @@ <string name="touchpad_tutorial_done_button" msgid="176168488821755503">"Gotovo"</string> <string name="touchpad_tutorial_gesture_done" msgid="4784438360736821255">"Odlično!"</string> <string name="touchpad_back_gesture_action_title" msgid="7199067250654332735">"Nazad"</string> - <string name="touchpad_back_gesture_guidance" msgid="4222430588599527272">"Da biste se vratili, prevucite ulevo ili udesno sa tri prsta bilo gde na tačpedu."</string> + <!-- no translation found for touchpad_back_gesture_guidance (6263750214998421587) --> + <skip /> + <!-- no translation found for touchpad_back_gesture_finished (5353616006999726249) --> + <skip /> <string name="touchpad_back_gesture_animation_content_description" msgid="2646107450922379918">"Tačped sa prikazom tri prsta koji se pomeraju udesno i ulevo"</string> <string name="touchpad_back_gesture_screen_animation_content_description" msgid="4036267494237748710">"Ekran uređaja sa prikazom animacije pokreta za nazad"</string> <string name="keyboard_backlight_dialog_title" msgid="8273102932345564724">"Pozadinsko osvetljenje tastature"</string> @@ -1388,28 +1396,16 @@ <string name="home_controls_dream_label" msgid="6567105701292324257">"Kontrole za dom"</string> <string name="home_controls_dream_description" msgid="4644150952104035789">"Brz pristup kontrolama za dom kao čuvaru ekrana"</string> <string name="volume_undo_action" msgid="5815519725211877114">"Opozovi"</string> - <!-- no translation found for back_edu_toast_content (4530314597378982956) --> - <skip /> - <!-- no translation found for home_edu_toast_content (3381071147871955415) --> - <skip /> - <!-- no translation found for overview_edu_toast_content (5797030644017804518) --> - <skip /> - <!-- no translation found for all_apps_edu_toast_content (8807496014667211562) --> - <skip /> - <!-- no translation found for back_edu_notification_title (5624780717751357278) --> - <skip /> - <!-- no translation found for back_edu_notification_content (2497557451540954068) --> - <skip /> - <!-- no translation found for home_edu_notification_title (6097902076909654045) --> - <skip /> - <!-- no translation found for home_edu_notification_content (6631697734535766588) --> - <skip /> - <!-- no translation found for overview_edu_notification_title (1265824157319562406) --> - <skip /> - <!-- no translation found for overview_edu_notification_content (3578204677648432500) --> - <skip /> - <!-- no translation found for all_apps_edu_notification_title (372262997265569063) --> - <skip /> - <!-- no translation found for all_apps_edu_notification_content (3255070575694025585) --> - <skip /> + <string name="back_edu_toast_content" msgid="4530314597378982956">"Da biste se vratili, prevucite ulevo ili udesno sa tri prsta na tačpedu"</string> + <string name="home_edu_toast_content" msgid="3381071147871955415">"Da biste otišli na početni ekran, prevucite nagore sa tri prsta na tačpedu"</string> + <string name="overview_edu_toast_content" msgid="5797030644017804518">"Da biste pregledali nedavne aplikacije, prevucite nagore i zadržite sa tri prsta na tačpedu"</string> + <string name="all_apps_edu_toast_content" msgid="8807496014667211562">"Da biste pogledali sve aplikacije, pritisnite taster radnji na tastaturi"</string> + <string name="back_edu_notification_title" msgid="5624780717751357278">"Koristite tačped da biste se vratili"</string> + <string name="back_edu_notification_content" msgid="2497557451540954068">"Prevucite ulevo ili udesno sa tri prsta. Dodirnite da biste videli više pokreta."</string> + <string name="home_edu_notification_title" msgid="6097902076909654045">"Koristite tačped da biste otišli na početni ekran"</string> + <string name="home_edu_notification_content" msgid="6631697734535766588">"Prevucite nagore sa tri prsta. Dodirnite da biste videli više pokreta."</string> + <string name="overview_edu_notification_title" msgid="1265824157319562406">"Koristite tačped da biste pregledali nedavne aplikacije"</string> + <string name="overview_edu_notification_content" msgid="3578204677648432500">"Prevucite nagore i zadržite sa tri prsta. Dodirnite da biste videli više pokreta."</string> + <string name="all_apps_edu_notification_title" msgid="372262997265569063">"Koristite tastaturu da biste pregledali sve aplikacije"</string> + <string name="all_apps_edu_notification_content" msgid="3255070575694025585">"Pritisnite taster radnji u bilo kom trenutku. Dodirnite da biste videli više pokreta."</string> </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 be48b3bcb916..df0b78664cba 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 @@ -56,11 +56,6 @@ <item msgid="5376619709702103243">"Isključeno"</item> <item msgid="4875147066469902392">"Uključeno"</item> </string-array> - <string-array name="tile_states_modes"> - <item msgid="7764936419245199023">"Nedostupno"</item> - <item msgid="2004750556637773692">"Isključeno"</item> - <item msgid="8968530753931637871">"Uključeno"</item> - </string-array> <string-array name="tile_states_flashlight"> <item msgid="3465257127433353857">"Nedostupno"</item> <item msgid="5044688398303285224">"Isključeno"</item> diff --git a/packages/SystemUI/res/values-be/strings.xml b/packages/SystemUI/res/values-be/strings.xml index eaa7c38c4866..0580d7ebb4a5 100644 --- a/packages/SystemUI/res/values-be/strings.xml +++ b/packages/SystemUI/res/values-be/strings.xml @@ -388,6 +388,9 @@ <string name="performance" msgid="6552785217174378320">"Прадукцыйнасць"</string> <string name="user_interface" msgid="3712869377953950887">"Карыстальніцкі інтэрфейс"</string> <string name="thermal" msgid="6758074791325414831">"Тэрмальныя паказчыкі"</string> + <string name="custom" msgid="3337456985275158299">"Карыстальніцкае значэнне"</string> + <string name="custom_trace_settings_dialog_title" msgid="2608570500144830554">"Карыстальніцкія налады трасіроўкі"</string> + <string name="restore_default" msgid="5259420807486239755">"Аднавіць стандартнае значэнне"</string> <string name="quick_settings_onehanded_label" msgid="2416537930246274991">"Рэжым кіравання адной рукой"</string> <string name="quick_settings_hearing_devices_label" msgid="7277170419679404129">"Слыхавыя апараты"</string> <string name="quick_settings_hearing_devices_connected" msgid="6519069502397037781">"Актыўныя"</string> @@ -429,9 +432,13 @@ <string name="zen_modes_dialog_title" msgid="4159138230418567383">"Прыярытэтныя рэжымы"</string> <string name="zen_modes_dialog_done" msgid="6654130880256438950">"Гатова"</string> <string name="zen_modes_dialog_settings" msgid="2310248023728936697">"Налады"</string> - <!-- no translation found for zen_mode_on (9085304934016242591) --> + <string name="zen_mode_on" msgid="9085304934016242591">"Уключана"</string> + <string name="zen_mode_off" msgid="1736604456618147306">"Выключана"</string> + <!-- no translation found for zen_mode_set_up (7457957033034460064) --> <skip /> - <!-- no translation found for zen_mode_off (1736604456618147306) --> + <!-- no translation found for zen_mode_no_manual_invocation (1769975741344633672) --> + <skip /> + <!-- no translation found for zen_mode_active_modes (1625850411578488856) --> <skip /> <string name="zen_priority_introduction" msgid="3159291973383796646">"Вас не будуць турбаваць гукі і вібрацыя, за выключэннем будзільнікаў, напамінаў, падзей і выбраных вамі абанентаў. Вы будзеце чуць усё, што ўключыце, у тым ліку музыку, відэа і гульні."</string> <string name="zen_alarms_introduction" msgid="3987266042682300470">"Вас не будуць турбаваць гукі і вібрацыя, за выключэннем будзільнікаў. Вы будзеце чуць усё, што ўключыце, у тым ліку музыку, відэа і гульні."</string> @@ -471,6 +478,8 @@ <string name="keyguard_indication_charging_time_slowly" msgid="301936949731705417">"<xliff:g id="PERCENTAGE">%2$s</xliff:g> • Ідзе павольная зарадка • Поўны зарад праз <xliff:g id="CHARGING_TIME_LEFT">%1$s</xliff:g>"</string> <string name="keyguard_indication_charging_time_dock" msgid="3149328898931741271">"<xliff:g id="PERCENTAGE">%2$s</xliff:g> • Ідзе зарадка • Поўны зарад праз <xliff:g id="CHARGING_TIME_LEFT">%1$s</xliff:g>"</string> <string name="accessibility_action_open_communal_hub" msgid="3081702792413787849">"Віджэты на экране блакіроўкі"</string> + <!-- no translation found for accessibility_announcement_communal_widget_added (6911593106099328271) --> + <skip /> <string name="communal_tutorial_indicator_text" msgid="4503010353591430123">"Правядзіце пальцам па экране ўлева, каб азнаёміцца з дапаможнікам"</string> <string name="cta_tile_button_to_open_widget_editor" msgid="3871562362382963878">"Наладзіць"</string> <string name="cta_tile_button_to_dismiss" msgid="3377597875997861754">"Закрыць"</string> @@ -499,8 +508,7 @@ <string name="accessibility_action_label_place_widget" msgid="1914197458644168978">"размясціць выбраны віджэт"</string> <string name="communal_widget_picker_title" msgid="1953369090475731663">"Віджэты на экране блакіроўкі"</string> <string name="communal_widget_picker_description" msgid="490515450110487871">"Віджэты на экране блакіроўкі будуць бачныя, нават калі планшэт заблакіраваны."</string> - <!-- no translation found for accessibility_action_label_unselect_widget (1041811747619468698) --> - <skip /> + <string name="accessibility_action_label_unselect_widget" msgid="1041811747619468698">"скасаваць выбар віджэта"</string> <string name="communal_widgets_disclaimer_title" msgid="1150954395585308868">"Віджэты на экране блакіроўкі"</string> <string name="communal_widgets_disclaimer_text" msgid="1423545475160506349">"Каб адкрыць праграму з дапамогай віджэта, вам неабходна будзе пацвердзіць сваю асобу. Таксама памятайце, што такія віджэты могуць пабачыць іншыя людзі, нават калі экран планшэта заблакіраваны. Некаторыя віджэты могуць не падыходзіць для выкарыстання на экране блакіроўкі, і дадаваць іх сюды можа быць небяспечна."</string> <string name="communal_widgets_disclaimer_button" msgid="4423059765740780753">"Зразумела"</string> @@ -557,10 +565,8 @@ <string name="media_projection_action_text" msgid="3634906766918186440">"Пачаць зараз"</string> <string name="empty_shade_text" msgid="8935967157319717412">"Апавяшчэнняў няма"</string> <string name="no_unseen_notif_text" msgid="395512586119868682">"Няма новых апавяшчэнняў"</string> - <!-- no translation found for adaptive_notification_edu_hun_title (7790738150177329960) --> - <skip /> - <!-- no translation found for adaptive_notification_edu_hun_text (7743367744129536610) --> - <skip /> + <string name="adaptive_notification_edu_hun_title" msgid="7790738150177329960">"Зніжэнне гучнасці апавяшчэнняў уключана"</string> + <string name="adaptive_notification_edu_hun_text" msgid="7743367744129536610">"Калі адначасова прыходзіць шмат апавяшчэнняў, гук прылады і абвестак зніжаецца на час да 2 хвілін."</string> <string name="go_to_adaptive_notification_settings" msgid="2423690125178298479">"Выключыць"</string> <string name="unlock_to_see_notif_text" msgid="7439033907167561227">"Разблакіруйце, каб убачыць усе апавяшчэнні"</string> <string name="quick_settings_disclosure_parental_controls" msgid="2114102871438223600">"Гэта прылада знаходзіцца пад кантролем бацькоў"</string> @@ -1226,7 +1232,6 @@ <string name="accessibility_fingerprint_bouncer" msgid="7189102492498735519">"Патрабуецца аўтэнтыфікацыя. Дакраніцеся да сканера адбіткаў пальцаў."</string> <string name="ongoing_phone_call_content_description" msgid="5332334388483099947">"Бягучы тэлефонны выклік"</string> <string name="mobile_data_settings_title" msgid="3955246641380064901">"Мабільная перадача даных"</string> - <string name="preference_summary_default_combination" msgid="8453246369903749670">"<xliff:g id="STATE">%1$s</xliff:g> / <xliff:g id="NETWORKMODE">%2$s</xliff:g>"</string> <string name="mobile_data_connection_active" msgid="944490013299018227">"Падключана"</string> <string name="mobile_data_temp_connection_active" msgid="4590222725908806824">"Падключана часова"</string> <string name="mobile_data_poor_connection" msgid="819617772268371434">"Нестабільнае падключэнне"</string> @@ -1380,7 +1385,10 @@ <string name="touchpad_tutorial_done_button" msgid="176168488821755503">"Гатова"</string> <string name="touchpad_tutorial_gesture_done" msgid="4784438360736821255">"Цудоўна!"</string> <string name="touchpad_back_gesture_action_title" msgid="7199067250654332735">"Назад"</string> - <string name="touchpad_back_gesture_guidance" msgid="4222430588599527272">"Каб вярнуцца на папярэдні экран, правядзіце трыма пальцамі ўлева або ўправа ў любым месцы сэнсарнай панэлі."</string> + <!-- no translation found for touchpad_back_gesture_guidance (6263750214998421587) --> + <skip /> + <!-- no translation found for touchpad_back_gesture_finished (5353616006999726249) --> + <skip /> <string name="touchpad_back_gesture_animation_content_description" msgid="2646107450922379918">"Паказваецца, як на сэнсарнай панэлі тры пальцы рухаюцца ўправа і ўлева"</string> <string name="touchpad_back_gesture_screen_animation_content_description" msgid="4036267494237748710">"На экране прылады паказваецца анімацыя жэста \"Назад\""</string> <string name="keyboard_backlight_dialog_title" msgid="8273102932345564724">"Падсветка клавіятуры"</string> @@ -1388,28 +1396,16 @@ <string name="home_controls_dream_label" msgid="6567105701292324257">"Кіраванне домам"</string> <string name="home_controls_dream_description" msgid="4644150952104035789">"Хуткі доступ да кіравання домам на застаўцы"</string> <string name="volume_undo_action" msgid="5815519725211877114">"Адрабіць"</string> - <!-- no translation found for back_edu_toast_content (4530314597378982956) --> - <skip /> - <!-- no translation found for home_edu_toast_content (3381071147871955415) --> - <skip /> - <!-- no translation found for overview_edu_toast_content (5797030644017804518) --> - <skip /> - <!-- no translation found for all_apps_edu_toast_content (8807496014667211562) --> - <skip /> - <!-- no translation found for back_edu_notification_title (5624780717751357278) --> - <skip /> - <!-- no translation found for back_edu_notification_content (2497557451540954068) --> - <skip /> - <!-- no translation found for home_edu_notification_title (6097902076909654045) --> - <skip /> - <!-- no translation found for home_edu_notification_content (6631697734535766588) --> - <skip /> - <!-- no translation found for overview_edu_notification_title (1265824157319562406) --> - <skip /> - <!-- no translation found for overview_edu_notification_content (3578204677648432500) --> - <skip /> - <!-- no translation found for all_apps_edu_notification_title (372262997265569063) --> - <skip /> - <!-- no translation found for all_apps_edu_notification_content (3255070575694025585) --> - <skip /> + <string name="back_edu_toast_content" msgid="4530314597378982956">"Каб вярнуцца, правядзіце па сэнсарнай панэлі трыма пальцамі ўлева ці ўправа"</string> + <string name="home_edu_toast_content" msgid="3381071147871955415">"Каб вярнуцца на галоўны экран, правядзіце па сэнсарнай панэлі трыма пальцамі ўверх"</string> + <string name="overview_edu_toast_content" msgid="5797030644017804518">"Для прагляду нядаўніх праграм правядзіце па сэнсарнай панэлі трыма пальцамі ўверх і затрымайцеся"</string> + <string name="all_apps_edu_toast_content" msgid="8807496014667211562">"Каб праглядзець усе праграмы, націсніце на клавішу дзеяння на клавіятуры"</string> + <string name="back_edu_notification_title" msgid="5624780717751357278">"Выкарыстайце сэнсарную панэль для вяртання"</string> + <string name="back_edu_notification_content" msgid="2497557451540954068">"Правядзіце ўлева ці ўправа трыма пальцамі. Націсніце, каб азнаёміцца з іншымі жэстамі."</string> + <string name="home_edu_notification_title" msgid="6097902076909654045">"Выкарыстайце сэнсарную панэль для вяртання на галоўны экран"</string> + <string name="home_edu_notification_content" msgid="6631697734535766588">"Правядзіце трыма пальцамі ўверх. Націсніце, каб азнаёміцца з іншымі жэстамі."</string> + <string name="overview_edu_notification_title" msgid="1265824157319562406">"Выкарыстайце сэнсарную панэль, каб праглядзець нядаўнія праграмы"</string> + <string name="overview_edu_notification_content" msgid="3578204677648432500">"Правядзіце трыма пальцамі ўверх і затрымайце пальцы. Націсніце, каб азнаёміцца з іншымі жэстамі."</string> + <string name="all_apps_edu_notification_title" msgid="372262997265569063">"Выкарыстайце клавіятуру для прагляду ўсіх праграм"</string> + <string name="all_apps_edu_notification_content" msgid="3255070575694025585">"Можна націснуць на клавішу дзеяння ў любы момант. Націсніце, каб азнаёміцца з іншымі жэстамі."</string> </resources> diff --git a/packages/SystemUI/res/values-be/tiles_states_strings.xml b/packages/SystemUI/res/values-be/tiles_states_strings.xml index aea701a66480..33e704cae0b1 100644 --- a/packages/SystemUI/res/values-be/tiles_states_strings.xml +++ b/packages/SystemUI/res/values-be/tiles_states_strings.xml @@ -56,11 +56,6 @@ <item msgid="5376619709702103243">"Выключана"</item> <item msgid="4875147066469902392">"Уключана"</item> </string-array> - <string-array name="tile_states_modes"> - <item msgid="7764936419245199023">"Недаступна"</item> - <item msgid="2004750556637773692">"Выключана"</item> - <item msgid="8968530753931637871">"Уключана"</item> - </string-array> <string-array name="tile_states_flashlight"> <item msgid="3465257127433353857">"Недаступна"</item> <item msgid="5044688398303285224">"Выключана"</item> diff --git a/packages/SystemUI/res/values-bg/strings.xml b/packages/SystemUI/res/values-bg/strings.xml index f515ea03a090..dfa9598a1062 100644 --- a/packages/SystemUI/res/values-bg/strings.xml +++ b/packages/SystemUI/res/values-bg/strings.xml @@ -388,6 +388,9 @@ <string name="performance" msgid="6552785217174378320">"Ефективност"</string> <string name="user_interface" msgid="3712869377953950887">"Потребителски интерфейс"</string> <string name="thermal" msgid="6758074791325414831">"Термално"</string> + <string name="custom" msgid="3337456985275158299">"Персонализирано"</string> + <string name="custom_trace_settings_dialog_title" msgid="2608570500144830554">"Настройки за персонализираната следа"</string> + <string name="restore_default" msgid="5259420807486239755">"Възстановяване на стандартната настройка"</string> <string name="quick_settings_onehanded_label" msgid="2416537930246274991">"Режим за работа с една ръка"</string> <string name="quick_settings_hearing_devices_label" msgid="7277170419679404129">"Слухови апарати"</string> <string name="quick_settings_hearing_devices_connected" msgid="6519069502397037781">"Активно"</string> @@ -429,9 +432,13 @@ <string name="zen_modes_dialog_title" msgid="4159138230418567383">"Приоритетни режими"</string> <string name="zen_modes_dialog_done" msgid="6654130880256438950">"Готово"</string> <string name="zen_modes_dialog_settings" msgid="2310248023728936697">"Настройки"</string> - <!-- no translation found for zen_mode_on (9085304934016242591) --> + <string name="zen_mode_on" msgid="9085304934016242591">"Вкл."</string> + <string name="zen_mode_off" msgid="1736604456618147306">"Изкл."</string> + <!-- no translation found for zen_mode_set_up (7457957033034460064) --> <skip /> - <!-- no translation found for zen_mode_off (1736604456618147306) --> + <!-- no translation found for zen_mode_no_manual_invocation (1769975741344633672) --> + <skip /> + <!-- no translation found for zen_mode_active_modes (1625850411578488856) --> <skip /> <string name="zen_priority_introduction" msgid="3159291973383796646">"Няма да бъдете обезпокоявани от звуци и вибрирания освен от будилници, напомняния, събития и обаждания от посочени от вас контакти. Пак ще чувате всичко, което изберете да се пусне, включително музика, видеоклипове и игри."</string> <string name="zen_alarms_introduction" msgid="3987266042682300470">"Няма да бъдете обезпокоявани от звуци и вибрирания освен от будилници. Ще чувате обаче всичко, което изберете пуснете, включително музика, видеоклипове и игри."</string> @@ -471,6 +478,8 @@ <string name="keyguard_indication_charging_time_slowly" msgid="301936949731705417">"<xliff:g id="PERCENTAGE">%2$s</xliff:g> • Зарежда се бавно • <xliff:g id="CHARGING_TIME_LEFT">%1$s</xliff:g> до пълно зареждане"</string> <string name="keyguard_indication_charging_time_dock" msgid="3149328898931741271">"<xliff:g id="PERCENTAGE">%2$s</xliff:g> • Зарежда се • <xliff:g id="CHARGING_TIME_LEFT">%1$s</xliff:g> до пълно зареждане"</string> <string name="accessibility_action_open_communal_hub" msgid="3081702792413787849">"Приспособления на заключения екран"</string> + <!-- no translation found for accessibility_announcement_communal_widget_added (6911593106099328271) --> + <skip /> <string name="communal_tutorial_indicator_text" msgid="4503010353591430123">"Прекарайте пръст наляво, за да стартирате общия урок"</string> <string name="cta_tile_button_to_open_widget_editor" msgid="3871562362382963878">"Персонализиране"</string> <string name="cta_tile_button_to_dismiss" msgid="3377597875997861754">"Отхвърляне"</string> @@ -499,8 +508,7 @@ <string name="accessibility_action_label_place_widget" msgid="1914197458644168978">"поставяне на избраното приспособление"</string> <string name="communal_widget_picker_title" msgid="1953369090475731663">"Приспособления за заключения екран"</string> <string name="communal_widget_picker_description" msgid="490515450110487871">"Всеки ще вижда приспособленията на закл. екран дори ако таблетът ви е заключен."</string> - <!-- no translation found for accessibility_action_label_unselect_widget (1041811747619468698) --> - <skip /> + <string name="accessibility_action_label_unselect_widget" msgid="1041811747619468698">"премахване на избора от приспособлението"</string> <string name="communal_widgets_disclaimer_title" msgid="1150954395585308868">"Приспособления за заключения екран"</string> <string name="communal_widgets_disclaimer_text" msgid="1423545475160506349">"За да отворите дадено приложение посредством приспособление, ще трябва да потвърдите, че това сте вие. Също така имайте предвид, че всеки ще вижда приспособленията дори когато таблетът ви е заключен. Възможно е някои от тях да не са предназначени за заключения екран и добавянето им на него може да е опасно."</string> <string name="communal_widgets_disclaimer_button" msgid="4423059765740780753">"Разбрах"</string> @@ -557,10 +565,8 @@ <string name="media_projection_action_text" msgid="3634906766918186440">"Стартиране сега"</string> <string name="empty_shade_text" msgid="8935967157319717412">"Няма известия"</string> <string name="no_unseen_notif_text" msgid="395512586119868682">"Няма нови известия"</string> - <!-- no translation found for adaptive_notification_edu_hun_title (7790738150177329960) --> - <skip /> - <!-- no translation found for adaptive_notification_edu_hun_text (7743367744129536610) --> - <skip /> + <string name="adaptive_notification_edu_hun_title" msgid="7790738150177329960">"Изчакването за известията е включено"</string> + <string name="adaptive_notification_edu_hun_text" msgid="7743367744129536610">"Силата на звука и сигналите на у-вото се намаляват за до 2 минути, когато получавате твърде много известия наведнъж."</string> <string name="go_to_adaptive_notification_settings" msgid="2423690125178298479">"Изключване"</string> <string name="unlock_to_see_notif_text" msgid="7439033907167561227">"Отключете за достъп до по-стари известия"</string> <string name="quick_settings_disclosure_parental_controls" msgid="2114102871438223600">"Това устройство се управлява от родителя ви"</string> @@ -1226,7 +1232,6 @@ <string name="accessibility_fingerprint_bouncer" msgid="7189102492498735519">"Изисква се удостоверяване на самоличността. За целта докоснете сензора за отпечатъци."</string> <string name="ongoing_phone_call_content_description" msgid="5332334388483099947">"Текущо телефонно обаждане"</string> <string name="mobile_data_settings_title" msgid="3955246641380064901">"Мобилни данни"</string> - <string name="preference_summary_default_combination" msgid="8453246369903749670">"<xliff:g id="STATE">%1$s</xliff:g>/<xliff:g id="NETWORKMODE">%2$s</xliff:g>"</string> <string name="mobile_data_connection_active" msgid="944490013299018227">"Свързано"</string> <string name="mobile_data_temp_connection_active" msgid="4590222725908806824">"Установена е временна връзка"</string> <string name="mobile_data_poor_connection" msgid="819617772268371434">"Слаба връзка"</string> @@ -1380,7 +1385,10 @@ <string name="touchpad_tutorial_done_button" msgid="176168488821755503">"Готово"</string> <string name="touchpad_tutorial_gesture_done" msgid="4784438360736821255">"Отлично!"</string> <string name="touchpad_back_gesture_action_title" msgid="7199067250654332735">"Назад"</string> - <string name="touchpad_back_gesture_guidance" msgid="4222430588599527272">"За да се върнете назад, прекарайте три пръста наляво или надясно по сензорния панел."</string> + <!-- no translation found for touchpad_back_gesture_guidance (6263750214998421587) --> + <skip /> + <!-- no translation found for touchpad_back_gesture_finished (5353616006999726249) --> + <skip /> <string name="touchpad_back_gesture_animation_content_description" msgid="2646107450922379918">"Сензорен панел, върху който три пръста се движат надясно и наляво"</string> <string name="touchpad_back_gesture_screen_animation_content_description" msgid="4036267494237748710">"Екран на устройство, показващ анимация за жеста за връщане назад"</string> <string name="keyboard_backlight_dialog_title" msgid="8273102932345564724">"Подсветка на клавиатурата"</string> @@ -1388,28 +1396,16 @@ <string name="home_controls_dream_label" msgid="6567105701292324257">"Контроли за дома"</string> <string name="home_controls_dream_description" msgid="4644150952104035789">"Достъп до контролите за дома ви като скрийнсейвър"</string> <string name="volume_undo_action" msgid="5815519725211877114">"Отмяна"</string> - <!-- no translation found for back_edu_toast_content (4530314597378982956) --> - <skip /> - <!-- no translation found for home_edu_toast_content (3381071147871955415) --> - <skip /> - <!-- no translation found for overview_edu_toast_content (5797030644017804518) --> - <skip /> - <!-- no translation found for all_apps_edu_toast_content (8807496014667211562) --> - <skip /> - <!-- no translation found for back_edu_notification_title (5624780717751357278) --> - <skip /> - <!-- no translation found for back_edu_notification_content (2497557451540954068) --> - <skip /> - <!-- no translation found for home_edu_notification_title (6097902076909654045) --> - <skip /> - <!-- no translation found for home_edu_notification_content (6631697734535766588) --> - <skip /> - <!-- no translation found for overview_edu_notification_title (1265824157319562406) --> - <skip /> - <!-- no translation found for overview_edu_notification_content (3578204677648432500) --> - <skip /> - <!-- no translation found for all_apps_edu_notification_title (372262997265569063) --> - <skip /> - <!-- no translation found for all_apps_edu_notification_content (3255070575694025585) --> - <skip /> + <string name="back_edu_toast_content" msgid="4530314597378982956">"За да се върнете назад, плъзнете три пръста наляво или надясно по сензорния панел"</string> + <string name="home_edu_toast_content" msgid="3381071147871955415">"За да преминете към началния екран, плъзнете нагоре по сензорния панел с три пръста"</string> + <string name="overview_edu_toast_content" msgid="5797030644017804518">"За да прегледате скорошните приложения, плъзнете нагоре по сензорния панел с три пръста и задръжте"</string> + <string name="all_apps_edu_toast_content" msgid="8807496014667211562">"За да прегледате всичките си приложения, натиснете клавиша за действия на клавиатурата си"</string> + <string name="back_edu_notification_title" msgid="5624780717751357278">"Използвайте сензорния панел, за да се върнете назад"</string> + <string name="back_edu_notification_content" msgid="2497557451540954068">"Плъзнете три пръста наляво или надясно. Докоснете, за да научите повече жестове."</string> + <string name="home_edu_notification_title" msgid="6097902076909654045">"Използвайте сензорния панел, за да преминете към началния екран"</string> + <string name="home_edu_notification_content" msgid="6631697734535766588">"Плъзнете нагоре с три пръста. Докоснете, за да научите повече жестове."</string> + <string name="overview_edu_notification_title" msgid="1265824157319562406">"Използвайте сензорния панел, за да прегледате скорошните приложения"</string> + <string name="overview_edu_notification_content" msgid="3578204677648432500">"Плъзнете нагоре с три пръста и задръжте. Докоснете, за да научите повече жестове."</string> + <string name="all_apps_edu_notification_title" msgid="372262997265569063">"Използвайте клавиатурата, за да прегледате всички приложения"</string> + <string name="all_apps_edu_notification_content" msgid="3255070575694025585">"Натиснете клавиша за действия по всяко време. Докоснете, за да научите повече жестове."</string> </resources> diff --git a/packages/SystemUI/res/values-bg/tiles_states_strings.xml b/packages/SystemUI/res/values-bg/tiles_states_strings.xml index 0258d2780a8d..e2fd65360020 100644 --- a/packages/SystemUI/res/values-bg/tiles_states_strings.xml +++ b/packages/SystemUI/res/values-bg/tiles_states_strings.xml @@ -56,11 +56,6 @@ <item msgid="5376619709702103243">"Изкл."</item> <item msgid="4875147066469902392">"Вкл."</item> </string-array> - <string-array name="tile_states_modes"> - <item msgid="7764936419245199023">"Не е налице"</item> - <item msgid="2004750556637773692">"Изкл."</item> - <item msgid="8968530753931637871">"Вкл."</item> - </string-array> <string-array name="tile_states_flashlight"> <item msgid="3465257127433353857">"Не е налице"</item> <item msgid="5044688398303285224">"Изкл."</item> diff --git a/packages/SystemUI/res/values-bn/strings.xml b/packages/SystemUI/res/values-bn/strings.xml index 2634892696a3..3f6c26922bb4 100644 --- a/packages/SystemUI/res/values-bn/strings.xml +++ b/packages/SystemUI/res/values-bn/strings.xml @@ -388,6 +388,9 @@ <string name="performance" msgid="6552785217174378320">"পারফর্ম্যান্স"</string> <string name="user_interface" msgid="3712869377953950887">"ইউজার ইন্টারফেস"</string> <string name="thermal" msgid="6758074791325414831">"থার্মাল"</string> + <string name="custom" msgid="3337456985275158299">"কাস্টম"</string> + <string name="custom_trace_settings_dialog_title" msgid="2608570500144830554">"কাস্টম ট্রেস সেটিংস"</string> + <string name="restore_default" msgid="5259420807486239755">"ডিফল্ট সেটিং ফিরিয়ে আনুন"</string> <string name="quick_settings_onehanded_label" msgid="2416537930246274991">"এক হাতে ব্যবহার করার মোড"</string> <string name="quick_settings_hearing_devices_label" msgid="7277170419679404129">"হিয়ারিং ডিভাইস"</string> <string name="quick_settings_hearing_devices_connected" msgid="6519069502397037781">"অ্যাক্টিভ"</string> @@ -431,6 +434,12 @@ <string name="zen_modes_dialog_settings" msgid="2310248023728936697">"সেটিংস"</string> <string name="zen_mode_on" msgid="9085304934016242591">"চালু আছে"</string> <string name="zen_mode_off" msgid="1736604456618147306">"বন্ধ আছে"</string> + <!-- no translation found for zen_mode_set_up (7457957033034460064) --> + <skip /> + <!-- no translation found for zen_mode_no_manual_invocation (1769975741344633672) --> + <skip /> + <!-- no translation found for zen_mode_active_modes (1625850411578488856) --> + <skip /> <string name="zen_priority_introduction" msgid="3159291973383796646">"অ্যালার্ম, রিমাইন্ডার, ইভেন্ট, এবং আপনার নির্দিষ্ট করে দেওয়া ব্যক্তিদের কল ছাড়া অন্য কোনও আওয়াজ বা ভাইব্রেশন হবে না। তবে সঙ্গীত, ভিডিও, এবং গেম সহ আপনি যা কিছু চালাবেন তার আওয়াজ শুনতে পাবেন।"</string> <string name="zen_alarms_introduction" msgid="3987266042682300470">"অ্যালার্ম ছাড়া অন্য কোনও আওয়াজ বা ভাইব্রেশন হবে না। তবে সঙ্গীত, ভিডিও, এবং গেম সহ আপনি যা কিছু চালাবেন তার আওয়াজ শুনতে পাবেন।"</string> <string name="zen_priority_customize_button" msgid="4119213187257195047">"কাস্টমাইজ করুন"</string> @@ -469,6 +478,8 @@ <string name="keyguard_indication_charging_time_slowly" msgid="301936949731705417">"<xliff:g id="PERCENTAGE">%2$s</xliff:g> • ধীরে চার্জ হচ্ছে • পুরো চার্জ হতে <xliff:g id="CHARGING_TIME_LEFT">%1$s</xliff:g> লাগবে"</string> <string name="keyguard_indication_charging_time_dock" msgid="3149328898931741271">"<xliff:g id="PERCENTAGE">%2$s</xliff:g> • চার্জ হচ্ছে • পুরো চার্জ হতে আরও <xliff:g id="CHARGING_TIME_LEFT">%1$s</xliff:g> সময় লাগবে"</string> <string name="accessibility_action_open_communal_hub" msgid="3081702792413787849">"লক স্ক্রিনে উইজেট"</string> + <!-- no translation found for accessibility_announcement_communal_widget_added (6911593106099328271) --> + <skip /> <string name="communal_tutorial_indicator_text" msgid="4503010353591430123">"কমিউনিটি টিউটোরিয়াল চালু করতে বাঁদিকে সোয়াইপ করুন"</string> <string name="cta_tile_button_to_open_widget_editor" msgid="3871562362382963878">"কাস্টমাইজ করুন"</string> <string name="cta_tile_button_to_dismiss" msgid="3377597875997861754">"বাতিল করুন"</string> @@ -554,10 +565,8 @@ <string name="media_projection_action_text" msgid="3634906766918186440">"এখন শুরু করুন"</string> <string name="empty_shade_text" msgid="8935967157319717412">"কোনও বিজ্ঞপ্তি নেই"</string> <string name="no_unseen_notif_text" msgid="395512586119868682">"নতুন কোনও বিজ্ঞপ্তি নেই"</string> - <!-- no translation found for adaptive_notification_edu_hun_title (7790738150177329960) --> - <skip /> - <!-- no translation found for adaptive_notification_edu_hun_text (7743367744129536610) --> - <skip /> + <string name="adaptive_notification_edu_hun_title" msgid="7790738150177329960">"নোটিফিকেশন কুলডাউন চালু আছে"</string> + <string name="adaptive_notification_edu_hun_text" msgid="7743367744129536610">"আপনি একসঙ্গে খুব বেশি বিজ্ঞপ্তি পেলে আপনার ডিভাইসের ভলিউম এবং সতর্কবার্তা সর্বাধিক ২ মিনিটের জন্য অটোমেটিক কমে যায়।"</string> <string name="go_to_adaptive_notification_settings" msgid="2423690125178298479">"বন্ধ করুন"</string> <string name="unlock_to_see_notif_text" msgid="7439033907167561227">"পুরনো বিজ্ঞপ্তি দেখতে আনলক করুন"</string> <string name="quick_settings_disclosure_parental_controls" msgid="2114102871438223600">"আপনার অভিভাবক এই ডিভাইস ম্যানেজ করেন"</string> @@ -1223,7 +1232,6 @@ <string name="accessibility_fingerprint_bouncer" msgid="7189102492498735519">"যাচাইকরণ করতে হবে। যাচাইকরণ করতে আঙুলের ছাপের সেন্সরে টাচ করুন।"</string> <string name="ongoing_phone_call_content_description" msgid="5332334388483099947">"ব্যবহারকারী এখন ফোনে কথা বলছেন"</string> <string name="mobile_data_settings_title" msgid="3955246641380064901">"মোবাইল ডেটা"</string> - <string name="preference_summary_default_combination" msgid="8453246369903749670">"<xliff:g id="STATE">%1$s</xliff:g> / <xliff:g id="NETWORKMODE">%2$s</xliff:g>"</string> <string name="mobile_data_connection_active" msgid="944490013299018227">"কানেক্ট করা আছে"</string> <string name="mobile_data_temp_connection_active" msgid="4590222725908806824">"সাময়িকভাবে কানেক্ট করা হয়েছে"</string> <string name="mobile_data_poor_connection" msgid="819617772268371434">"খারাপ কানেকশন"</string> @@ -1377,7 +1385,10 @@ <string name="touchpad_tutorial_done_button" msgid="176168488821755503">"হয়ে গেছে"</string> <string name="touchpad_tutorial_gesture_done" msgid="4784438360736821255">"অসাধারণ!"</string> <string name="touchpad_back_gesture_action_title" msgid="7199067250654332735">"ফিরে যান"</string> - <string name="touchpad_back_gesture_guidance" msgid="4222430588599527272">"ফিরে যেতে, টাচপ্যাডের যেকোনও জায়গায় তিনটি আঙুল দিয়ে ডান বা বাঁদিকে সোয়াইপ করুন।"</string> + <!-- no translation found for touchpad_back_gesture_guidance (6263750214998421587) --> + <skip /> + <!-- no translation found for touchpad_back_gesture_finished (5353616006999726249) --> + <skip /> <string name="touchpad_back_gesture_animation_content_description" msgid="2646107450922379918">"টাচপ্যাডে, তিনটি আঙুল ডান ও বাঁদিকে সরানো দেখানো হচ্ছে"</string> <string name="touchpad_back_gesture_screen_animation_content_description" msgid="4036267494237748710">"ডিভাইসের স্ক্রিনে ফিরে যাওয়ার জেসচারের অ্যানিমেশন দেখানো হচ্ছে"</string> <string name="keyboard_backlight_dialog_title" msgid="8273102932345564724">"কীবোর্ড ব্যাকলাইট"</string> diff --git a/packages/SystemUI/res/values-bn/tiles_states_strings.xml b/packages/SystemUI/res/values-bn/tiles_states_strings.xml index 4935f32bb532..6e4dfbfbf745 100644 --- a/packages/SystemUI/res/values-bn/tiles_states_strings.xml +++ b/packages/SystemUI/res/values-bn/tiles_states_strings.xml @@ -56,11 +56,6 @@ <item msgid="5376619709702103243">"বন্ধ আছে"</item> <item msgid="4875147066469902392">"চালু আছে"</item> </string-array> - <string-array name="tile_states_modes"> - <item msgid="7764936419245199023">"উপলভ্য নেই"</item> - <item msgid="2004750556637773692">"বন্ধ আছে"</item> - <item msgid="8968530753931637871">"চালু আছে"</item> - </string-array> <string-array name="tile_states_flashlight"> <item msgid="3465257127433353857">"উপলভ্য নেই"</item> <item msgid="5044688398303285224">"বন্ধ আছে"</item> diff --git a/packages/SystemUI/res/values-bs/strings.xml b/packages/SystemUI/res/values-bs/strings.xml index 08052a449a2d..2bc13c0fac5e 100644 --- a/packages/SystemUI/res/values-bs/strings.xml +++ b/packages/SystemUI/res/values-bs/strings.xml @@ -388,6 +388,9 @@ <string name="performance" msgid="6552785217174378320">"Performanse"</string> <string name="user_interface" msgid="3712869377953950887">"Korisnički interfejs"</string> <string name="thermal" msgid="6758074791325414831">"Termalno"</string> + <string name="custom" msgid="3337456985275158299">"Prilagođeno"</string> + <string name="custom_trace_settings_dialog_title" msgid="2608570500144830554">"Prilagodite postavke traga"</string> + <string name="restore_default" msgid="5259420807486239755">"Vrati zadano"</string> <string name="quick_settings_onehanded_label" msgid="2416537930246274991">"Način rada jednom rukom"</string> <string name="quick_settings_hearing_devices_label" msgid="7277170419679404129">"Slušni aparati"</string> <string name="quick_settings_hearing_devices_connected" msgid="6519069502397037781">"Aktivno"</string> @@ -429,9 +432,13 @@ <string name="zen_modes_dialog_title" msgid="4159138230418567383">"Prioritetni načini rada"</string> <string name="zen_modes_dialog_done" msgid="6654130880256438950">"Gotovo"</string> <string name="zen_modes_dialog_settings" msgid="2310248023728936697">"Postavke"</string> - <!-- no translation found for zen_mode_on (9085304934016242591) --> + <string name="zen_mode_on" msgid="9085304934016242591">"Uključeno"</string> + <string name="zen_mode_off" msgid="1736604456618147306">"Isključeno"</string> + <!-- no translation found for zen_mode_set_up (7457957033034460064) --> <skip /> - <!-- no translation found for zen_mode_off (1736604456618147306) --> + <!-- no translation found for zen_mode_no_manual_invocation (1769975741344633672) --> + <skip /> + <!-- no translation found for zen_mode_active_modes (1625850411578488856) --> <skip /> <string name="zen_priority_introduction" msgid="3159291973383796646">"Neće vas ometati zvukovi i vibracije, osim alarma, podsjetnika, događaja i pozivalaca koje odredite. I dalje ćete čuti sve što ste odabrali za reprodukciju, uključujući muziku, videozapise i igre."</string> <string name="zen_alarms_introduction" msgid="3987266042682300470">"Neće vas ometati zvukovi i vibracije, osim alarma. I dalje ćete čuti sve što izaberete za reprodukciju, uključujući muziku, videozapise i igre."</string> @@ -471,6 +478,8 @@ <string name="keyguard_indication_charging_time_slowly" msgid="301936949731705417">"<xliff:g id="PERCENTAGE">%2$s</xliff:g> • Sporo punjenje • Potpuna napunjenost za <xliff:g id="CHARGING_TIME_LEFT">%1$s</xliff:g>"</string> <string name="keyguard_indication_charging_time_dock" msgid="3149328898931741271">"<xliff:g id="PERCENTAGE">%2$s</xliff:g> • Punjenje • Potpuna napunjenost za <xliff:g id="CHARGING_TIME_LEFT">%1$s</xliff:g>"</string> <string name="accessibility_action_open_communal_hub" msgid="3081702792413787849">"Vidžeti na zaključanom ekranu"</string> + <!-- no translation found for accessibility_announcement_communal_widget_added (6911593106099328271) --> + <skip /> <string name="communal_tutorial_indicator_text" msgid="4503010353591430123">"Prevucite ulijevo da pokrenete zajednički vodič"</string> <string name="cta_tile_button_to_open_widget_editor" msgid="3871562362382963878">"Prilagodite"</string> <string name="cta_tile_button_to_dismiss" msgid="3377597875997861754">"Odbaci"</string> @@ -499,8 +508,7 @@ <string name="accessibility_action_label_place_widget" msgid="1914197458644168978">"postavljanje odabranog vidžeta"</string> <string name="communal_widget_picker_title" msgid="1953369090475731663">"Vidžeti na zaključanom ekranu"</string> <string name="communal_widget_picker_description" msgid="490515450110487871">"Svi mogu pregledati vidžete na zaključanom ekranu, čak i ako je tablet zaključan."</string> - <!-- no translation found for accessibility_action_label_unselect_widget (1041811747619468698) --> - <skip /> + <string name="accessibility_action_label_unselect_widget" msgid="1041811747619468698">"poništavanje odabira vidžeta"</string> <string name="communal_widgets_disclaimer_title" msgid="1150954395585308868">"Vidžeti zaključanog ekrana"</string> <string name="communal_widgets_disclaimer_text" msgid="1423545475160506349">"Da otvorite aplikaciju pomoću vidžeta, morat ćete potvrditi identitet. Također imajte na umu da ih svako može pregledati, čak i ako je tablet zaključan. Neki vidžeti možda nisu namijenjeni za vaš zaključani ekran i njihovo dodavanje ovdje možda nije sigurno."</string> <string name="communal_widgets_disclaimer_button" msgid="4423059765740780753">"Razumijem"</string> @@ -557,10 +565,8 @@ <string name="media_projection_action_text" msgid="3634906766918186440">"Započni odmah"</string> <string name="empty_shade_text" msgid="8935967157319717412">"Nema obavještenja"</string> <string name="no_unseen_notif_text" msgid="395512586119868682">"Nema novih obavještenja"</string> - <!-- no translation found for adaptive_notification_edu_hun_title (7790738150177329960) --> - <skip /> - <!-- no translation found for adaptive_notification_edu_hun_text (7743367744129536610) --> - <skip /> + <string name="adaptive_notification_edu_hun_title" msgid="7790738150177329960">"Stišavanje obavještenja je uključeno"</string> + <string name="adaptive_notification_edu_hun_text" msgid="7743367744129536610">"Jačina zvuka uređaja i obavještenja se automatski stišavaju do 2 minute kada odjednom dobijete previše obavještenja."</string> <string name="go_to_adaptive_notification_settings" msgid="2423690125178298479">"Isključi"</string> <string name="unlock_to_see_notif_text" msgid="7439033907167561227">"Otključajte da vidite starija obavještenja"</string> <string name="quick_settings_disclosure_parental_controls" msgid="2114102871438223600">"Ovim uređajem upravlja tvoj roditelj"</string> @@ -1226,7 +1232,6 @@ <string name="accessibility_fingerprint_bouncer" msgid="7189102492498735519">"Potrebna je autentifikacija. Dodirnite senzor za otisak prsta da autentificirate."</string> <string name="ongoing_phone_call_content_description" msgid="5332334388483099947">"Telefonski poziv u toku"</string> <string name="mobile_data_settings_title" msgid="3955246641380064901">"Prijenos podataka na mobilnoj mreži"</string> - <string name="preference_summary_default_combination" msgid="8453246369903749670">"<xliff:g id="STATE">%1$s</xliff:g>/<xliff:g id="NETWORKMODE">%2$s</xliff:g>"</string> <string name="mobile_data_connection_active" msgid="944490013299018227">"Povezano"</string> <string name="mobile_data_temp_connection_active" msgid="4590222725908806824">"Privremeno povezano"</string> <string name="mobile_data_poor_connection" msgid="819617772268371434">"Slaba veza"</string> @@ -1380,7 +1385,10 @@ <string name="touchpad_tutorial_done_button" msgid="176168488821755503">"Gotovo"</string> <string name="touchpad_tutorial_gesture_done" msgid="4784438360736821255">"Sjajno!"</string> <string name="touchpad_back_gesture_action_title" msgid="7199067250654332735">"Nazad"</string> - <string name="touchpad_back_gesture_guidance" msgid="4222430588599527272">"Da se vratite, prevucite ulijevo ili udesno s tri prsta bilo gdje na dodirnoj podlozi."</string> + <!-- no translation found for touchpad_back_gesture_guidance (6263750214998421587) --> + <skip /> + <!-- no translation found for touchpad_back_gesture_finished (5353616006999726249) --> + <skip /> <string name="touchpad_back_gesture_animation_content_description" msgid="2646107450922379918">"Dodirna podloga prikazuje tri prsta koji se pomjeraju desno-lijevo"</string> <string name="touchpad_back_gesture_screen_animation_content_description" msgid="4036267494237748710">"Ekran uređaja pokazuje animaciju pokreta unazad"</string> <string name="keyboard_backlight_dialog_title" msgid="8273102932345564724">"Pozadinsko osvjetljenje tastature"</string> @@ -1388,28 +1396,16 @@ <string name="home_controls_dream_label" msgid="6567105701292324257">"Kontrole za dom"</string> <string name="home_controls_dream_description" msgid="4644150952104035789">"Brzo pristupajte kontrolama za dom putem čuvara ekrana"</string> <string name="volume_undo_action" msgid="5815519725211877114">"Poništi"</string> - <!-- no translation found for back_edu_toast_content (4530314597378982956) --> - <skip /> - <!-- no translation found for home_edu_toast_content (3381071147871955415) --> - <skip /> - <!-- no translation found for overview_edu_toast_content (5797030644017804518) --> - <skip /> - <!-- no translation found for all_apps_edu_toast_content (8807496014667211562) --> - <skip /> - <!-- no translation found for back_edu_notification_title (5624780717751357278) --> - <skip /> - <!-- no translation found for back_edu_notification_content (2497557451540954068) --> - <skip /> - <!-- no translation found for home_edu_notification_title (6097902076909654045) --> - <skip /> - <!-- no translation found for home_edu_notification_content (6631697734535766588) --> - <skip /> - <!-- no translation found for overview_edu_notification_title (1265824157319562406) --> - <skip /> - <!-- no translation found for overview_edu_notification_content (3578204677648432500) --> - <skip /> - <!-- no translation found for all_apps_edu_notification_title (372262997265569063) --> - <skip /> - <!-- no translation found for all_apps_edu_notification_content (3255070575694025585) --> - <skip /> + <string name="back_edu_toast_content" msgid="4530314597378982956">"Da se vratite, prevucite ulijevo ili udesno s tri prsta na dodirnoj podlozi"</string> + <string name="home_edu_toast_content" msgid="3381071147871955415">"Da se vratite na početnu stranicu, prevucite nagore s tri prsta na dodirnoj podlozi"</string> + <string name="overview_edu_toast_content" msgid="5797030644017804518">"Da pregledate nedavne aplikacije, prevucite nagore i zadržite s tri prsta na dodirnoj podlozi"</string> + <string name="all_apps_edu_toast_content" msgid="8807496014667211562">"Da pregledate sve aplikacije, pritisnite tipku radnji na tastaturi"</string> + <string name="back_edu_notification_title" msgid="5624780717751357278">"Koristite dodirnu podlogu da se vratite"</string> + <string name="back_edu_notification_content" msgid="2497557451540954068">"Prevucite ulijevo ili udesno s tri prsta. Dodirnite da saznate za više pokreta."</string> + <string name="home_edu_notification_title" msgid="6097902076909654045">"Koristite dodirnu podlogu da se vratite na početnu stranicu"</string> + <string name="home_edu_notification_content" msgid="6631697734535766588">"Prevucite nagore s tri prsta. Dodirnite da saznate za više pokreta."</string> + <string name="overview_edu_notification_title" msgid="1265824157319562406">"Koristite dodirnu podlogu da pregledate nedavne aplikacije"</string> + <string name="overview_edu_notification_content" msgid="3578204677648432500">"Prevucite nagore i zadržite s tri prsta. Dodirnite da saznate za više pokreta."</string> + <string name="all_apps_edu_notification_title" msgid="372262997265569063">"Koristite tastaturu da pregledate sve aplikacije"</string> + <string name="all_apps_edu_notification_content" msgid="3255070575694025585">"Pritisnite tipku radnji bilo kada. Dodirnite da saznate za više pokreta."</string> </resources> diff --git a/packages/SystemUI/res/values-bs/tiles_states_strings.xml b/packages/SystemUI/res/values-bs/tiles_states_strings.xml index be48b3bcb916..df0b78664cba 100644 --- a/packages/SystemUI/res/values-bs/tiles_states_strings.xml +++ b/packages/SystemUI/res/values-bs/tiles_states_strings.xml @@ -56,11 +56,6 @@ <item msgid="5376619709702103243">"Isključeno"</item> <item msgid="4875147066469902392">"Uključeno"</item> </string-array> - <string-array name="tile_states_modes"> - <item msgid="7764936419245199023">"Nedostupno"</item> - <item msgid="2004750556637773692">"Isključeno"</item> - <item msgid="8968530753931637871">"Uključeno"</item> - </string-array> <string-array name="tile_states_flashlight"> <item msgid="3465257127433353857">"Nedostupno"</item> <item msgid="5044688398303285224">"Isključeno"</item> diff --git a/packages/SystemUI/res/values-ca/strings.xml b/packages/SystemUI/res/values-ca/strings.xml index a76ee9fb91ce..a9ab9fc7789c 100644 --- a/packages/SystemUI/res/values-ca/strings.xml +++ b/packages/SystemUI/res/values-ca/strings.xml @@ -388,6 +388,9 @@ <string name="performance" msgid="6552785217174378320">"Rendiment"</string> <string name="user_interface" msgid="3712869377953950887">"Interfície d\'usuari"</string> <string name="thermal" msgid="6758074791325414831">"Tèrmic"</string> + <string name="custom" msgid="3337456985275158299">"Personalitzat"</string> + <string name="custom_trace_settings_dialog_title" msgid="2608570500144830554">"Configuració de traça personalitzada"</string> + <string name="restore_default" msgid="5259420807486239755">"Restaura la configuració predeterminada"</string> <string name="quick_settings_onehanded_label" msgid="2416537930246274991">"Mode d\'una mà"</string> <string name="quick_settings_hearing_devices_label" msgid="7277170419679404129">"Audiòfons"</string> <string name="quick_settings_hearing_devices_connected" msgid="6519069502397037781">"Actiu"</string> @@ -429,9 +432,13 @@ <string name="zen_modes_dialog_title" msgid="4159138230418567383">"Modes prioritaris"</string> <string name="zen_modes_dialog_done" msgid="6654130880256438950">"Fet"</string> <string name="zen_modes_dialog_settings" msgid="2310248023728936697">"Configuració"</string> - <!-- no translation found for zen_mode_on (9085304934016242591) --> + <string name="zen_mode_on" msgid="9085304934016242591">"Activat"</string> + <string name="zen_mode_off" msgid="1736604456618147306">"Desactivat"</string> + <!-- no translation found for zen_mode_set_up (7457957033034460064) --> <skip /> - <!-- no translation found for zen_mode_off (1736604456618147306) --> + <!-- no translation found for zen_mode_no_manual_invocation (1769975741344633672) --> + <skip /> + <!-- no translation found for zen_mode_active_modes (1625850411578488856) --> <skip /> <string name="zen_priority_introduction" msgid="3159291973383796646">"No t\'interromprà cap so ni cap vibració, tret dels de les alarmes, recordatoris, esdeveniments i trucades de les persones que especifiquis. Continuaràs sentint tot allò que decideixis reproduir, com ara música, vídeos i jocs."</string> <string name="zen_alarms_introduction" msgid="3987266042682300470">"No t\'interromprà cap so ni cap vibració, tret dels de les alarmes. Continuaràs sentint tot allò que decideixis reproduir, com ara música, vídeos i jocs."</string> @@ -471,6 +478,8 @@ <string name="keyguard_indication_charging_time_slowly" msgid="301936949731705417">"<xliff:g id="PERCENTAGE">%2$s</xliff:g> • Carregant lentament • Es completarà d\'aquí a <xliff:g id="CHARGING_TIME_LEFT">%1$s</xliff:g>"</string> <string name="keyguard_indication_charging_time_dock" msgid="3149328898931741271">"<xliff:g id="PERCENTAGE">%2$s</xliff:g> • S\'està carregant • Es completarà d\'aquí a <xliff:g id="CHARGING_TIME_LEFT">%1$s</xliff:g>"</string> <string name="accessibility_action_open_communal_hub" msgid="3081702792413787849">"Widgets a la pantalla de bloqueig"</string> + <!-- no translation found for accessibility_announcement_communal_widget_added (6911593106099328271) --> + <skip /> <string name="communal_tutorial_indicator_text" msgid="4503010353591430123">"Llisca cap a l\'esquerra per iniciar el tutorial de la comunitat"</string> <string name="cta_tile_button_to_open_widget_editor" msgid="3871562362382963878">"Personalitza"</string> <string name="cta_tile_button_to_dismiss" msgid="3377597875997861754">"Ignora"</string> @@ -499,8 +508,7 @@ <string name="accessibility_action_label_place_widget" msgid="1914197458644168978">"col·loca el widget seleccionat"</string> <string name="communal_widget_picker_title" msgid="1953369090475731663">"Widgets de la pantalla de bloqueig"</string> <string name="communal_widget_picker_description" msgid="490515450110487871">"Tothom pot veure widgets a la pantalla de bloqueig, fins i tot amb la tauleta bloquejada."</string> - <!-- no translation found for accessibility_action_label_unselect_widget (1041811747619468698) --> - <skip /> + <string name="accessibility_action_label_unselect_widget" msgid="1041811747619468698">"desselecciona el widget"</string> <string name="communal_widgets_disclaimer_title" msgid="1150954395585308868">"Widgets de la pantalla de bloqueig"</string> <string name="communal_widgets_disclaimer_text" msgid="1423545475160506349">"Per obrir una aplicació utilitzant un widget, necessitaràs verificar la teva identitat. També has de tenir en compte que qualsevol persona pot veure els widgets, fins i tot quan la tauleta està bloquejada. És possible que alguns widgets no estiguin pensats per a la pantalla de bloqueig i que no sigui segur afegir-los-hi."</string> <string name="communal_widgets_disclaimer_button" msgid="4423059765740780753">"Entesos"</string> @@ -557,10 +565,8 @@ <string name="media_projection_action_text" msgid="3634906766918186440">"Comença ara"</string> <string name="empty_shade_text" msgid="8935967157319717412">"No hi ha cap notificació"</string> <string name="no_unseen_notif_text" msgid="395512586119868682">"No hi ha cap notificació nova"</string> - <!-- no translation found for adaptive_notification_edu_hun_title (7790738150177329960) --> - <skip /> - <!-- no translation found for adaptive_notification_edu_hun_text (7743367744129536610) --> - <skip /> + <string name="adaptive_notification_edu_hun_title" msgid="7790738150177329960">"La moderació de notificacions està activada"</string> + <string name="adaptive_notification_edu_hun_text" msgid="7743367744129536610">"El volum i les alertes del dispositiu es redueixen automàticament durant 2 minuts quan reps massa notificacions alhora."</string> <string name="go_to_adaptive_notification_settings" msgid="2423690125178298479">"Desactiva"</string> <string name="unlock_to_see_notif_text" msgid="7439033907167561227">"Desbloqueja per veure notif. anteriors"</string> <string name="quick_settings_disclosure_parental_controls" msgid="2114102871438223600">"Els teus pares gestionen aquest dispositiu"</string> @@ -1226,7 +1232,6 @@ <string name="accessibility_fingerprint_bouncer" msgid="7189102492498735519">"Autenticació necessària. Toca el sensor d\'empremtes digitals per autenticar-te."</string> <string name="ongoing_phone_call_content_description" msgid="5332334388483099947">"Trucada en curs"</string> <string name="mobile_data_settings_title" msgid="3955246641380064901">"Dades mòbils"</string> - <string name="preference_summary_default_combination" msgid="8453246369903749670">"<xliff:g id="STATE">%1$s</xliff:g>/<xliff:g id="NETWORKMODE">%2$s</xliff:g>"</string> <string name="mobile_data_connection_active" msgid="944490013299018227">"Connectat"</string> <string name="mobile_data_temp_connection_active" msgid="4590222725908806824">"Connexió temporal"</string> <string name="mobile_data_poor_connection" msgid="819617772268371434">"Connexió feble"</string> @@ -1380,7 +1385,10 @@ <string name="touchpad_tutorial_done_button" msgid="176168488821755503">"Fet"</string> <string name="touchpad_tutorial_gesture_done" msgid="4784438360736821255">"Ben fet!"</string> <string name="touchpad_back_gesture_action_title" msgid="7199067250654332735">"Torna"</string> - <string name="touchpad_back_gesture_guidance" msgid="4222430588599527272">"Per tornar enrere, llisca cap a l\'esquerra o cap a la dreta amb tres dits en qualsevol lloc del ratolí tàctil."</string> + <!-- no translation found for touchpad_back_gesture_guidance (6263750214998421587) --> + <skip /> + <!-- no translation found for touchpad_back_gesture_finished (5353616006999726249) --> + <skip /> <string name="touchpad_back_gesture_animation_content_description" msgid="2646107450922379918">"Ratolí tàctil que mostra tres dits que es mouen cap a la dreta i cap a l\'esquerra"</string> <string name="touchpad_back_gesture_screen_animation_content_description" msgid="4036267494237748710">"Pantalla del dispositiu que mostra l\'animació del gest per anar enrere"</string> <string name="keyboard_backlight_dialog_title" msgid="8273102932345564724">"Retroil·luminació del teclat"</string> @@ -1388,28 +1396,16 @@ <string name="home_controls_dream_label" msgid="6567105701292324257">"Controls de la llar"</string> <string name="home_controls_dream_description" msgid="4644150952104035789">"Utilitza controls de la llar com a estalvi de pantalla"</string> <string name="volume_undo_action" msgid="5815519725211877114">"Desfés"</string> - <!-- no translation found for back_edu_toast_content (4530314597378982956) --> - <skip /> - <!-- no translation found for home_edu_toast_content (3381071147871955415) --> - <skip /> - <!-- no translation found for overview_edu_toast_content (5797030644017804518) --> - <skip /> - <!-- no translation found for all_apps_edu_toast_content (8807496014667211562) --> - <skip /> - <!-- no translation found for back_edu_notification_title (5624780717751357278) --> - <skip /> - <!-- no translation found for back_edu_notification_content (2497557451540954068) --> - <skip /> - <!-- no translation found for home_edu_notification_title (6097902076909654045) --> - <skip /> - <!-- no translation found for home_edu_notification_content (6631697734535766588) --> - <skip /> - <!-- no translation found for overview_edu_notification_title (1265824157319562406) --> - <skip /> - <!-- no translation found for overview_edu_notification_content (3578204677648432500) --> - <skip /> - <!-- no translation found for all_apps_edu_notification_title (372262997265569063) --> - <skip /> - <!-- no translation found for all_apps_edu_notification_content (3255070575694025585) --> - <skip /> + <string name="back_edu_toast_content" msgid="4530314597378982956">"Per tornar enrere, llisca tres dits cap a l\'esquerra o cap a la dreta al ratolí tàctil"</string> + <string name="home_edu_toast_content" msgid="3381071147871955415">"Per anar a la pantalla d\'inici, llisca tres dits cap amunt al ratolí tàctil"</string> + <string name="overview_edu_toast_content" msgid="5797030644017804518">"Per veure les aplicacions recents, llisca cap amunt amb tres dits i mantén premut al ratolí tàctil"</string> + <string name="all_apps_edu_toast_content" msgid="8807496014667211562">"Per veure totes les aplicacions, prem la tecla d\'acció al teclat"</string> + <string name="back_edu_notification_title" msgid="5624780717751357278">"Utilitza el ratolí tàctil per tornar enrere"</string> + <string name="back_edu_notification_content" msgid="2497557451540954068">"Fes lliscar tres dits cap a l\'esquerra o cap a la dreta. Toca per aprendre més gestos."</string> + <string name="home_edu_notification_title" msgid="6097902076909654045">"Utilitza el ratolí tàctil per anar a la pantalla d\'inici"</string> + <string name="home_edu_notification_content" msgid="6631697734535766588">"Llisca tres dits cap amunt. Toca per aprendre més gestos."</string> + <string name="overview_edu_notification_title" msgid="1265824157319562406">"Utilitza el ratolí tàctil per veure les aplicacions recents"</string> + <string name="overview_edu_notification_content" msgid="3578204677648432500">"Llisca cap amunt amb tres dits i mantén premut. Toca per aprendre més gestos."</string> + <string name="all_apps_edu_notification_title" msgid="372262997265569063">"Utilitza el teclat per veure totes les aplicacions"</string> + <string name="all_apps_edu_notification_content" msgid="3255070575694025585">"Prem la tecla d\'acció en qualsevol moment. Toca per aprendre més gestos."</string> </resources> diff --git a/packages/SystemUI/res/values-ca/tiles_states_strings.xml b/packages/SystemUI/res/values-ca/tiles_states_strings.xml index d11dd32d5a82..67eb853c9ee6 100644 --- a/packages/SystemUI/res/values-ca/tiles_states_strings.xml +++ b/packages/SystemUI/res/values-ca/tiles_states_strings.xml @@ -56,11 +56,6 @@ <item msgid="5376619709702103243">"Desactivat"</item> <item msgid="4875147066469902392">"Activat"</item> </string-array> - <string-array name="tile_states_modes"> - <item msgid="7764936419245199023">"No disponible"</item> - <item msgid="2004750556637773692">"Desactivat"</item> - <item msgid="8968530753931637871">"Activat"</item> - </string-array> <string-array name="tile_states_flashlight"> <item msgid="3465257127433353857">"No disponible"</item> <item msgid="5044688398303285224">"Desactivat"</item> diff --git a/packages/SystemUI/res/values-cs/strings.xml b/packages/SystemUI/res/values-cs/strings.xml index 12ef55cf5df6..194057a7309c 100644 --- a/packages/SystemUI/res/values-cs/strings.xml +++ b/packages/SystemUI/res/values-cs/strings.xml @@ -388,6 +388,9 @@ <string name="performance" msgid="6552785217174378320">"Výkon"</string> <string name="user_interface" msgid="3712869377953950887">"Uživatelské rozhraní"</string> <string name="thermal" msgid="6758074791325414831">"Termovize"</string> + <string name="custom" msgid="3337456985275158299">"Vlastní"</string> + <string name="custom_trace_settings_dialog_title" msgid="2608570500144830554">"Vlastní nastavení trasování"</string> + <string name="restore_default" msgid="5259420807486239755">"Obnovit výchozí"</string> <string name="quick_settings_onehanded_label" msgid="2416537930246274991">"Režim jedné ruky"</string> <string name="quick_settings_hearing_devices_label" msgid="7277170419679404129">"Naslouchátka"</string> <string name="quick_settings_hearing_devices_connected" msgid="6519069502397037781">"Aktivní"</string> @@ -429,9 +432,13 @@ <string name="zen_modes_dialog_title" msgid="4159138230418567383">"Režimy priority"</string> <string name="zen_modes_dialog_done" msgid="6654130880256438950">"Hotovo"</string> <string name="zen_modes_dialog_settings" msgid="2310248023728936697">"Nastavení"</string> - <!-- no translation found for zen_mode_on (9085304934016242591) --> + <string name="zen_mode_on" msgid="9085304934016242591">"Zapnuto"</string> + <string name="zen_mode_off" msgid="1736604456618147306">"Vypnuto"</string> + <!-- no translation found for zen_mode_set_up (7457957033034460064) --> <skip /> - <!-- no translation found for zen_mode_off (1736604456618147306) --> + <!-- no translation found for zen_mode_no_manual_invocation (1769975741344633672) --> + <skip /> + <!-- no translation found for zen_mode_active_modes (1625850411578488856) --> <skip /> <string name="zen_priority_introduction" msgid="3159291973383796646">"Nebudou vás rušit zvuky ani vibrace s výjimkou budíků, upozornění, událostí a volajících, které zadáte. Nadále uslyšíte veškerý obsah, který si sami pustíte (např. hudba, videa nebo hry)."</string> <string name="zen_alarms_introduction" msgid="3987266042682300470">"Nebudou vás rušit zvuky ani vibrace s výjimkou budíků. Nadále uslyšíte veškerý obsah, který si sami pustíte (např. hudba, videa nebo hry)."</string> @@ -471,6 +478,8 @@ <string name="keyguard_indication_charging_time_slowly" msgid="301936949731705417">"<xliff:g id="PERCENTAGE">%2$s</xliff:g> • Pomalé nabíjení • Plně nabito za <xliff:g id="CHARGING_TIME_LEFT">%1$s</xliff:g>"</string> <string name="keyguard_indication_charging_time_dock" msgid="3149328898931741271">"<xliff:g id="PERCENTAGE">%2$s</xliff:g> • Nabíjení • Plně nabito za <xliff:g id="CHARGING_TIME_LEFT">%1$s</xliff:g>"</string> <string name="accessibility_action_open_communal_hub" msgid="3081702792413787849">"Widgety na obrazovce uzamčení"</string> + <!-- no translation found for accessibility_announcement_communal_widget_added (6911593106099328271) --> + <skip /> <string name="communal_tutorial_indicator_text" msgid="4503010353591430123">"Přejetím doleva spustíte komunitní výukový program"</string> <string name="cta_tile_button_to_open_widget_editor" msgid="3871562362382963878">"Přizpůsobit"</string> <string name="cta_tile_button_to_dismiss" msgid="3377597875997861754">"Zavřít"</string> @@ -499,8 +508,7 @@ <string name="accessibility_action_label_place_widget" msgid="1914197458644168978">"umístit vybraný widget"</string> <string name="communal_widget_picker_title" msgid="1953369090475731663">"Widgety na obrazovce uzamčení"</string> <string name="communal_widget_picker_description" msgid="490515450110487871">"Widgety na obrazovce uzamčení může zobrazit kdokoli, i když je tablet uzamčen."</string> - <!-- no translation found for accessibility_action_label_unselect_widget (1041811747619468698) --> - <skip /> + <string name="accessibility_action_label_unselect_widget" msgid="1041811747619468698">"zrušit výběr widgetu"</string> <string name="communal_widgets_disclaimer_title" msgid="1150954395585308868">"Widgety na obrazovce uzamčení"</string> <string name="communal_widgets_disclaimer_text" msgid="1423545475160506349">"K otevření aplikace pomocí widgetu budete muset ověřit svou totožnost. Také mějte na paměti, že widgety uvidí kdokoli, i když tablet bude uzamčen. Některé widgety nemusí být pro obrazovku uzamčení určeny a nemusí být bezpečné je na ni přidat."</string> <string name="communal_widgets_disclaimer_button" msgid="4423059765740780753">"Rozumím"</string> @@ -557,10 +565,8 @@ <string name="media_projection_action_text" msgid="3634906766918186440">"Spustit"</string> <string name="empty_shade_text" msgid="8935967157319717412">"Žádná oznámení"</string> <string name="no_unseen_notif_text" msgid="395512586119868682">"Žádná nová oznámení"</string> - <!-- no translation found for adaptive_notification_edu_hun_title (7790738150177329960) --> - <skip /> - <!-- no translation found for adaptive_notification_edu_hun_text (7743367744129536610) --> - <skip /> + <string name="adaptive_notification_edu_hun_title" msgid="7790738150177329960">"Je zapnuté zeslabení oznámení"</string> + <string name="adaptive_notification_edu_hun_text" msgid="7743367744129536610">"Když dostanete příliš mnoho oznámení najednou, až na dvě minuty se sníží hlasitost zařízení a oznámení se omezí."</string> <string name="go_to_adaptive_notification_settings" msgid="2423690125178298479">"Vypnout"</string> <string name="unlock_to_see_notif_text" msgid="7439033907167561227">"Starší oznámení se zobrazí po odemknutí"</string> <string name="quick_settings_disclosure_parental_controls" msgid="2114102871438223600">"Toto zařízení spravuje rodič"</string> @@ -1226,7 +1232,6 @@ <string name="accessibility_fingerprint_bouncer" msgid="7189102492498735519">"Je vyžadováno ověření. Dotkněte se snímače otisků prstů."</string> <string name="ongoing_phone_call_content_description" msgid="5332334388483099947">"Probíhající hovor"</string> <string name="mobile_data_settings_title" msgid="3955246641380064901">"Mobilní data"</string> - <string name="preference_summary_default_combination" msgid="8453246369903749670">"<xliff:g id="STATE">%1$s</xliff:g> / <xliff:g id="NETWORKMODE">%2$s</xliff:g>"</string> <string name="mobile_data_connection_active" msgid="944490013299018227">"Připojeno"</string> <string name="mobile_data_temp_connection_active" msgid="4590222725908806824">"Dočasně připojeno"</string> <string name="mobile_data_poor_connection" msgid="819617772268371434">"Nekvalitní připojení"</string> @@ -1380,7 +1385,10 @@ <string name="touchpad_tutorial_done_button" msgid="176168488821755503">"Hotovo"</string> <string name="touchpad_tutorial_gesture_done" msgid="4784438360736821255">"Výborně!"</string> <string name="touchpad_back_gesture_action_title" msgid="7199067250654332735">"Zpět"</string> - <string name="touchpad_back_gesture_guidance" msgid="4222430588599527272">"Pokud se chcete vrátit zpět, stačí kdekoli na touchpadu přejet třemi prsty doleva nebo doprava."</string> + <!-- no translation found for touchpad_back_gesture_guidance (6263750214998421587) --> + <skip /> + <!-- no translation found for touchpad_back_gesture_finished (5353616006999726249) --> + <skip /> <string name="touchpad_back_gesture_animation_content_description" msgid="2646107450922379918">"Touchpad se třemi prsty, které se pohybují doprava a doleva"</string> <string name="touchpad_back_gesture_screen_animation_content_description" msgid="4036267494237748710">"Obrazovka zařízení s animaci gesta k vrácení zpět"</string> <string name="keyboard_backlight_dialog_title" msgid="8273102932345564724">"Podsvícení klávesnice"</string> @@ -1388,28 +1396,16 @@ <string name="home_controls_dream_label" msgid="6567105701292324257">"Ovládání domácnosti"</string> <string name="home_controls_dream_description" msgid="4644150952104035789">"Rychlý přístup k funkcím, jako je spořič obrazovky"</string> <string name="volume_undo_action" msgid="5815519725211877114">"Vrátit zpět"</string> - <!-- no translation found for back_edu_toast_content (4530314597378982956) --> - <skip /> - <!-- no translation found for home_edu_toast_content (3381071147871955415) --> - <skip /> - <!-- no translation found for overview_edu_toast_content (5797030644017804518) --> - <skip /> - <!-- no translation found for all_apps_edu_toast_content (8807496014667211562) --> - <skip /> - <!-- no translation found for back_edu_notification_title (5624780717751357278) --> - <skip /> - <!-- no translation found for back_edu_notification_content (2497557451540954068) --> - <skip /> - <!-- no translation found for home_edu_notification_title (6097902076909654045) --> - <skip /> - <!-- no translation found for home_edu_notification_content (6631697734535766588) --> - <skip /> - <!-- no translation found for overview_edu_notification_title (1265824157319562406) --> - <skip /> - <!-- no translation found for overview_edu_notification_content (3578204677648432500) --> - <skip /> - <!-- no translation found for all_apps_edu_notification_title (372262997265569063) --> - <skip /> - <!-- no translation found for all_apps_edu_notification_content (3255070575694025585) --> - <skip /> + <string name="back_edu_toast_content" msgid="4530314597378982956">"Pokud se chcete vrátit zpět, přejeďte po touchpadu třemi prsty doleva nebo doprava"</string> + <string name="home_edu_toast_content" msgid="3381071147871955415">"Pokud se chcete vrátit domů, přejeďte po touchpadu třemi prsty nahoru"</string> + <string name="overview_edu_toast_content" msgid="5797030644017804518">"Pokud chcete zobrazit poslední aplikace, přejeďte na touchpadu třemi prsty nahoru a podržte je"</string> + <string name="all_apps_edu_toast_content" msgid="8807496014667211562">"Pokud chcete zobrazit všechny aplikace, stiskněte na klávesnici akční klávesu"</string> + <string name="back_edu_notification_title" msgid="5624780717751357278">"Návrat zpět pomocí touchpadu"</string> + <string name="back_edu_notification_content" msgid="2497557451540954068">"Přejeďte třemi prsty doleva nebo doprava. Další gesta zjistíte klepnutím."</string> + <string name="home_edu_notification_title" msgid="6097902076909654045">"Návrat domů pomocí touchpadu"</string> + <string name="home_edu_notification_content" msgid="6631697734535766588">"Přejeďte třemi prsty nahoru. Další gesta zjistíte klepnutím."</string> + <string name="overview_edu_notification_title" msgid="1265824157319562406">"Zobrazení posledních aplikací pomocí touchpadu"</string> + <string name="overview_edu_notification_content" msgid="3578204677648432500">"Přejeďte třemi prsty nahoru a podržte je. Další gesta zjistíte klepnutím."</string> + <string name="all_apps_edu_notification_title" msgid="372262997265569063">"Zobrazení všech aplikací pomocí klávesnice"</string> + <string name="all_apps_edu_notification_content" msgid="3255070575694025585">"Kdykoli stiskněte akční klávesu. Další gesta zjistíte klepnutím."</string> </resources> diff --git a/packages/SystemUI/res/values-cs/tiles_states_strings.xml b/packages/SystemUI/res/values-cs/tiles_states_strings.xml index 71c95694e09d..ae533a8623ec 100644 --- a/packages/SystemUI/res/values-cs/tiles_states_strings.xml +++ b/packages/SystemUI/res/values-cs/tiles_states_strings.xml @@ -56,11 +56,6 @@ <item msgid="5376619709702103243">"Vypnuto"</item> <item msgid="4875147066469902392">"Zapnuto"</item> </string-array> - <string-array name="tile_states_modes"> - <item msgid="7764936419245199023">"Nedostupné"</item> - <item msgid="2004750556637773692">"Vypnuto"</item> - <item msgid="8968530753931637871">"Zapnuto"</item> - </string-array> <string-array name="tile_states_flashlight"> <item msgid="3465257127433353857">"Nedostupné"</item> <item msgid="5044688398303285224">"Vypnuto"</item> diff --git a/packages/SystemUI/res/values-da/strings.xml b/packages/SystemUI/res/values-da/strings.xml index ef9ef95fe502..ba1babf21ebe 100644 --- a/packages/SystemUI/res/values-da/strings.xml +++ b/packages/SystemUI/res/values-da/strings.xml @@ -131,7 +131,7 @@ <string name="screenrecord_stop_dialog_message_specific_app" msgid="5995770227684523244">"Du optager i øjeblikket <xliff:g id="APP_NAME">%1$s</xliff:g>"</string> <string name="screenrecord_stop_dialog_button" msgid="2883812564938194350">"Stop optagelse"</string> <string name="share_to_app_chip_accessibility_label" msgid="4210256229976947065">"Skærmen deles"</string> - <string name="share_to_app_stop_dialog_title" msgid="9212915050910250438">"Stop skærmdelingen?"</string> + <string name="share_to_app_stop_dialog_title" msgid="9212915050910250438">"Vil du stoppe skærmdelingen?"</string> <string name="share_to_app_stop_dialog_message_entire_screen_with_host_app" msgid="522823522115375414">"Du deler i øjeblikket hele skærmen med <xliff:g id="HOST_APP_NAME">%1$s</xliff:g>"</string> <string name="share_to_app_stop_dialog_message_entire_screen" msgid="5090115386271179270">"Du deler i øjeblikket hele skærmen med en app"</string> <string name="share_to_app_stop_dialog_message_single_app_specific" msgid="5923772039347985172">"Du deler i øjeblikket <xliff:g id="APP_BEING_SHARED_NAME">%1$s</xliff:g>"</string> @@ -218,13 +218,13 @@ <string name="biometric_re_enroll_notification_content" msgid="8685925877186288180">"Dette er påkrævet for at forbedre sikkerheden og ydeevnen"</string> <string name="fingerprint_re_enroll_notification_title" msgid="4539432429683916604">"Konfigurer fingeroplåsning igen"</string> <string name="fingerprint_re_enroll_notification_name" msgid="630798657797645704">"Fingeroplåsning"</string> - <string name="fingerprint_re_enroll_dialog_title" msgid="3526033128113925780">"Konfigurer fingeroplåsning"</string> + <string name="fingerprint_re_enroll_dialog_title" msgid="3526033128113925780">"Konfigurer fingeroplåsning"</string> <string name="fingerprint_re_enroll_dialog_content" msgid="4866561176695984879">"Hvis du vil konfigurere fingeroplåsning igen, bliver dine nuværende fingeraftryksbilleder og -modeller slettet.\n\nNår de er slettet, skal du konfigurere fingeroplåsning igen for at bruge dit fingeraftryk til at låse din telefon op eller verificere din identitet."</string> <string name="fingerprint_re_enroll_dialog_content_singular" msgid="3083663339787381218">"Hvis du vil konfigurere fingeroplåsning igen, bliver dine nuværende fingeraftryksbilleder og -modeller slettet.\n\nNår de er slettet, skal du konfigurere fingeroplåsning igen for at bruge dit fingeraftryk til at låse din telefon op eller verificere din identitet."</string> <string name="fingerprint_reenroll_failure_dialog_content" msgid="4733768492747300666">"Fingeroplåsning kunne ikke konfigureres. Gå til Indstillinger for at prøve igen."</string> <string name="face_re_enroll_notification_title" msgid="1850838867718410520">"Konfigurer ansigtsoplåsning igen"</string> <string name="face_re_enroll_notification_name" msgid="7384545252206120659">"Ansigtsoplåsning"</string> - <string name="face_re_enroll_dialog_title" msgid="6392173708176069994">"Konfigurer ansigtsoplåsning"</string> + <string name="face_re_enroll_dialog_title" msgid="6392173708176069994">"Konfigurer ansigtsoplåsning"</string> <string name="face_re_enroll_dialog_content" msgid="7353502359464038511">"Hvis du vil konfigurere ansigtsoplåsning igen, bliver din nuværende ansigtsmodel slettet.\n\nDu skal konfigurere funktionen igen for at bruge ansigtsgenkendelse til at låse din telefon op."</string> <string name="face_reenroll_failure_dialog_content" msgid="7073947334397236935">"Ansigtsoplåsning kunne ikke konfigureres. Gå til Indstillinger for at prøve igen."</string> <string name="fingerprint_dialog_touch_sensor" msgid="2817887108047658975">"Sæt fingeren på fingeraftrykssensoren"</string> @@ -388,6 +388,9 @@ <string name="performance" msgid="6552785217174378320">"Ydeevne"</string> <string name="user_interface" msgid="3712869377953950887">"Brugerflade"</string> <string name="thermal" msgid="6758074791325414831">"Termisk"</string> + <string name="custom" msgid="3337456985275158299">"Tilpas"</string> + <string name="custom_trace_settings_dialog_title" msgid="2608570500144830554">"Tilpas indstillinger for registrering"</string> + <string name="restore_default" msgid="5259420807486239755">"Gendan standard"</string> <string name="quick_settings_onehanded_label" msgid="2416537930246274991">"Enhåndstilstand"</string> <string name="quick_settings_hearing_devices_label" msgid="7277170419679404129">"Høreapparater"</string> <string name="quick_settings_hearing_devices_connected" msgid="6519069502397037781">"Aktivt"</string> @@ -429,9 +432,13 @@ <string name="zen_modes_dialog_title" msgid="4159138230418567383">"Tilstande med prioritet"</string> <string name="zen_modes_dialog_done" msgid="6654130880256438950">"Udfør"</string> <string name="zen_modes_dialog_settings" msgid="2310248023728936697">"Indstillinger"</string> - <!-- no translation found for zen_mode_on (9085304934016242591) --> + <string name="zen_mode_on" msgid="9085304934016242591">"Til"</string> + <string name="zen_mode_off" msgid="1736604456618147306">"Fra"</string> + <!-- no translation found for zen_mode_set_up (7457957033034460064) --> <skip /> - <!-- no translation found for zen_mode_off (1736604456618147306) --> + <!-- no translation found for zen_mode_no_manual_invocation (1769975741344633672) --> + <skip /> + <!-- no translation found for zen_mode_active_modes (1625850411578488856) --> <skip /> <string name="zen_priority_introduction" msgid="3159291973383796646">"Du bliver ikke forstyrret af lyde eller vibrationer, undtagen fra alarmer, påmindelser, begivenheder og opkald fra udvalgte personer, du selv angiver. Du kan stadig høre alt, du vælger at afspille, f.eks. musik, videoer og spil."</string> <string name="zen_alarms_introduction" msgid="3987266042682300470">"Du bliver ikke forstyrret af lyde eller vibrationer, undtagen fra alarmer. Du kan stadig høre alt, du vælger at afspille, f.eks. musik, videoer og spil."</string> @@ -471,6 +478,8 @@ <string name="keyguard_indication_charging_time_slowly" msgid="301936949731705417">"<xliff:g id="PERCENTAGE">%2$s</xliff:g> • Oplader langsomt • Fuldt opladet om <xliff:g id="CHARGING_TIME_LEFT">%1$s</xliff:g>"</string> <string name="keyguard_indication_charging_time_dock" msgid="3149328898931741271">"<xliff:g id="PERCENTAGE">%2$s</xliff:g> • Oplader • Fuldt opladet om <xliff:g id="CHARGING_TIME_LEFT">%1$s</xliff:g>"</string> <string name="accessibility_action_open_communal_hub" msgid="3081702792413787849">"Widgets på låseskærmen"</string> + <!-- no translation found for accessibility_announcement_communal_widget_added (6911593106099328271) --> + <skip /> <string name="communal_tutorial_indicator_text" msgid="4503010353591430123">"Stryg mod venstre for at starte den fælles vejledning"</string> <string name="cta_tile_button_to_open_widget_editor" msgid="3871562362382963878">"Tilpas"</string> <string name="cta_tile_button_to_dismiss" msgid="3377597875997861754">"Luk"</string> @@ -499,8 +508,7 @@ <string name="accessibility_action_label_place_widget" msgid="1914197458644168978">"placer valgt widget"</string> <string name="communal_widget_picker_title" msgid="1953369090475731663">"Widgets på låseskærmen"</string> <string name="communal_widget_picker_description" msgid="490515450110487871">"Alle kan se widgets på din låseskærm, også selvom din tablet er låst."</string> - <!-- no translation found for accessibility_action_label_unselect_widget (1041811747619468698) --> - <skip /> + <string name="accessibility_action_label_unselect_widget" msgid="1041811747619468698">"fjern markering af widget"</string> <string name="communal_widgets_disclaimer_title" msgid="1150954395585308868">"Widgets på låseskærmen"</string> <string name="communal_widgets_disclaimer_text" msgid="1423545475160506349">"Hvis du vil åbne en app ved hjælp af en widget, skal du verificere din identitet. Husk også, at alle kan se dem, også når din tablet er låst. Nogle widgets er muligvis ikke beregnet til låseskærmen, og det kan være usikkert at tilføje dem her."</string> <string name="communal_widgets_disclaimer_button" msgid="4423059765740780753">"OK"</string> @@ -557,10 +565,8 @@ <string name="media_projection_action_text" msgid="3634906766918186440">"Start nu"</string> <string name="empty_shade_text" msgid="8935967157319717412">"Ingen notifikationer"</string> <string name="no_unseen_notif_text" msgid="395512586119868682">"Ingen nye notifikationer"</string> - <!-- no translation found for adaptive_notification_edu_hun_title (7790738150177329960) --> - <skip /> - <!-- no translation found for adaptive_notification_edu_hun_text (7743367744129536610) --> - <skip /> + <string name="adaptive_notification_edu_hun_title" msgid="7790738150177329960">"Dæmpning af notifikationer er aktiveret"</string> + <string name="adaptive_notification_edu_hun_text" msgid="7743367744129536610">"Enheden skruer automatisk ned for lydstyrken og minimerer underretninger på skærmen i op til 2 minutter, når du får for mange notifikationer på én gang."</string> <string name="go_to_adaptive_notification_settings" msgid="2423690125178298479">"Deaktiver"</string> <string name="unlock_to_see_notif_text" msgid="7439033907167561227">"Lås op for at se ældre notifikationer"</string> <string name="quick_settings_disclosure_parental_controls" msgid="2114102871438223600">"Denne enhed administreres af din forælder"</string> @@ -1226,7 +1232,6 @@ <string name="accessibility_fingerprint_bouncer" msgid="7189102492498735519">"Godkendelse er påkrævet. Sæt fingeren på fingeraftrykssensoren for at godkende."</string> <string name="ongoing_phone_call_content_description" msgid="5332334388483099947">"Igangværende telefonopkald"</string> <string name="mobile_data_settings_title" msgid="3955246641380064901">"Mobildata"</string> - <string name="preference_summary_default_combination" msgid="8453246369903749670">"<xliff:g id="STATE">%1$s</xliff:g>/<xliff:g id="NETWORKMODE">%2$s</xliff:g>"</string> <string name="mobile_data_connection_active" msgid="944490013299018227">"Forbundet"</string> <string name="mobile_data_temp_connection_active" msgid="4590222725908806824">"Midlertidigt forbundet"</string> <string name="mobile_data_poor_connection" msgid="819617772268371434">"Dårlig forbindelse"</string> @@ -1380,7 +1385,10 @@ <string name="touchpad_tutorial_done_button" msgid="176168488821755503">"Udfør"</string> <string name="touchpad_tutorial_gesture_done" msgid="4784438360736821255">"Sådan!"</string> <string name="touchpad_back_gesture_action_title" msgid="7199067250654332735">"Gå tilbage"</string> - <string name="touchpad_back_gesture_guidance" msgid="4222430588599527272">"Du kan gå tilbage ved at stryge mod venstre eller højre med tre fingre et vilkårligt sted på touchpladen."</string> + <!-- no translation found for touchpad_back_gesture_guidance (6263750214998421587) --> + <skip /> + <!-- no translation found for touchpad_back_gesture_finished (5353616006999726249) --> + <skip /> <string name="touchpad_back_gesture_animation_content_description" msgid="2646107450922379918">"Touchplade viser tre fingre, der bevæger sig til højre og venstre"</string> <string name="touchpad_back_gesture_screen_animation_content_description" msgid="4036267494237748710">"Enhedsskærm, der viser en animation, som demonstrerer, hvordan man går tilbage"</string> <string name="keyboard_backlight_dialog_title" msgid="8273102932345564724">"Tastaturets baggrundslys"</string> @@ -1388,28 +1396,16 @@ <string name="home_controls_dream_label" msgid="6567105701292324257">"Hjemmestyring"</string> <string name="home_controls_dream_description" msgid="4644150952104035789">"Tilgå hurtigt hjemmestyring via din pauseskærm"</string> <string name="volume_undo_action" msgid="5815519725211877114">"Fortryd"</string> - <!-- no translation found for back_edu_toast_content (4530314597378982956) --> - <skip /> - <!-- no translation found for home_edu_toast_content (3381071147871955415) --> - <skip /> - <!-- no translation found for overview_edu_toast_content (5797030644017804518) --> - <skip /> - <!-- no translation found for all_apps_edu_toast_content (8807496014667211562) --> - <skip /> - <!-- no translation found for back_edu_notification_title (5624780717751357278) --> - <skip /> - <!-- no translation found for back_edu_notification_content (2497557451540954068) --> - <skip /> - <!-- no translation found for home_edu_notification_title (6097902076909654045) --> - <skip /> - <!-- no translation found for home_edu_notification_content (6631697734535766588) --> - <skip /> - <!-- no translation found for overview_edu_notification_title (1265824157319562406) --> - <skip /> - <!-- no translation found for overview_edu_notification_content (3578204677648432500) --> - <skip /> - <!-- no translation found for all_apps_edu_notification_title (372262997265569063) --> - <skip /> - <!-- no translation found for all_apps_edu_notification_content (3255070575694025585) --> - <skip /> + <string name="back_edu_toast_content" msgid="4530314597378982956">"Du kan gå tilbage ved at stryge til venstre eller højre med tre fingre på touchpladen"</string> + <string name="home_edu_toast_content" msgid="3381071147871955415">"Du kan gå til startskærmen ved at stryge opad med tre fingre på touchpladen"</string> + <string name="overview_edu_toast_content" msgid="5797030644017804518">"Du kan se nyligt brugte apps ved at stryge opad og holde tre fingre nede på touchpladen"</string> + <string name="all_apps_edu_toast_content" msgid="8807496014667211562">"Du kan se alle dine apps ved at trykke på handlingstasten på dit tastatur"</string> + <string name="back_edu_notification_title" msgid="5624780717751357278">"Brug din touchplade til at gå tilbage"</string> + <string name="back_edu_notification_content" msgid="2497557451540954068">"Stryg til venstre eller højre med tre fingre. Tryk for at lære flere bevægelser."</string> + <string name="home_edu_notification_title" msgid="6097902076909654045">"Brug din touchplade til at gå til startskærmen"</string> + <string name="home_edu_notification_content" msgid="6631697734535766588">"Stryg opad med tre fingre. Tryk for at lære flere bevægelser."</string> + <string name="overview_edu_notification_title" msgid="1265824157319562406">"Brug din touchplade til at se nyligt brugte apps"</string> + <string name="overview_edu_notification_content" msgid="3578204677648432500">"Stryg opad, og hold tre fingre nede. Tryk for at lære flere bevægelser."</string> + <string name="all_apps_edu_notification_title" msgid="372262997265569063">"Brug dit tastatur til at se alle apps"</string> + <string name="all_apps_edu_notification_content" msgid="3255070575694025585">"Tryk på handlingstasten når som helst. Tryk for at lære flere bevægelser."</string> </resources> diff --git a/packages/SystemUI/res/values-da/tiles_states_strings.xml b/packages/SystemUI/res/values-da/tiles_states_strings.xml index 9b11f52902ba..2c3b0535cb33 100644 --- a/packages/SystemUI/res/values-da/tiles_states_strings.xml +++ b/packages/SystemUI/res/values-da/tiles_states_strings.xml @@ -56,11 +56,6 @@ <item msgid="5376619709702103243">"Fra"</item> <item msgid="4875147066469902392">"Til"</item> </string-array> - <string-array name="tile_states_modes"> - <item msgid="7764936419245199023">"Ikke tilgængelig"</item> - <item msgid="2004750556637773692">"Fra"</item> - <item msgid="8968530753931637871">"Til"</item> - </string-array> <string-array name="tile_states_flashlight"> <item msgid="3465257127433353857">"Ikke tilgængelig"</item> <item msgid="5044688398303285224">"Fra"</item> diff --git a/packages/SystemUI/res/values-de/strings.xml b/packages/SystemUI/res/values-de/strings.xml index c9b449d65c16..62ede78ff214 100644 --- a/packages/SystemUI/res/values-de/strings.xml +++ b/packages/SystemUI/res/values-de/strings.xml @@ -388,6 +388,9 @@ <string name="performance" msgid="6552785217174378320">"Leistung"</string> <string name="user_interface" msgid="3712869377953950887">"Benutzeroberfläche"</string> <string name="thermal" msgid="6758074791325414831">"Überhitzung"</string> + <string name="custom" msgid="3337456985275158299">"Benutzerdefiniert"</string> + <string name="custom_trace_settings_dialog_title" msgid="2608570500144830554">"Benutzerdefinierte Trace-Einstellungen"</string> + <string name="restore_default" msgid="5259420807486239755">"Standard wiederherstellen"</string> <string name="quick_settings_onehanded_label" msgid="2416537930246274991">"Einhandmodus"</string> <string name="quick_settings_hearing_devices_label" msgid="7277170419679404129">"Hörgeräte"</string> <string name="quick_settings_hearing_devices_connected" msgid="6519069502397037781">"Aktiv"</string> @@ -429,9 +432,13 @@ <string name="zen_modes_dialog_title" msgid="4159138230418567383">"Prioritätsmodi"</string> <string name="zen_modes_dialog_done" msgid="6654130880256438950">"Fertig"</string> <string name="zen_modes_dialog_settings" msgid="2310248023728936697">"Einstellungen"</string> - <!-- no translation found for zen_mode_on (9085304934016242591) --> + <string name="zen_mode_on" msgid="9085304934016242591">"An"</string> + <string name="zen_mode_off" msgid="1736604456618147306">"Aus"</string> + <!-- no translation found for zen_mode_set_up (7457957033034460064) --> <skip /> - <!-- no translation found for zen_mode_off (1736604456618147306) --> + <!-- no translation found for zen_mode_no_manual_invocation (1769975741344633672) --> + <skip /> + <!-- no translation found for zen_mode_active_modes (1625850411578488856) --> <skip /> <string name="zen_priority_introduction" msgid="3159291973383796646">"Klingeltöne und die Vibration werden deaktiviert, außer für Weckrufe, Erinnerungen, Termine sowie Anrufe von zuvor von dir festgelegten Personen. Du hörst jedoch weiterhin Sound, wenn du dir Musik anhörst, Videos ansiehst oder Spiele spielst."</string> <string name="zen_alarms_introduction" msgid="3987266042682300470">"Klingeltöne und die Vibration werden deaktiviert, außer für Weckrufe. Du hörst jedoch weiterhin Sound, wenn du dir Musik anhörst, Videos ansiehst oder Spiele spielst."</string> @@ -471,6 +478,8 @@ <string name="keyguard_indication_charging_time_slowly" msgid="301936949731705417">"<xliff:g id="PERCENTAGE">%2$s</xliff:g> • Wird langsam geladen • Voll in <xliff:g id="CHARGING_TIME_LEFT">%1$s</xliff:g>"</string> <string name="keyguard_indication_charging_time_dock" msgid="3149328898931741271">"<xliff:g id="PERCENTAGE">%2$s</xliff:g> • Wird geladen • Voll in <xliff:g id="CHARGING_TIME_LEFT">%1$s</xliff:g>"</string> <string name="accessibility_action_open_communal_hub" msgid="3081702792413787849">"Widgets auf dem Sperrbildschirm"</string> + <!-- no translation found for accessibility_announcement_communal_widget_added (6911593106099328271) --> + <skip /> <string name="communal_tutorial_indicator_text" msgid="4503010353591430123">"Wische nach links, um das gemeinsame Tutorial zu starten"</string> <string name="cta_tile_button_to_open_widget_editor" msgid="3871562362382963878">"Anpassen"</string> <string name="cta_tile_button_to_dismiss" msgid="3377597875997861754">"Schließen"</string> @@ -499,8 +508,7 @@ <string name="accessibility_action_label_place_widget" msgid="1914197458644168978">"ausgewähltes Widget in den Bearbeitungsmodus versetzen"</string> <string name="communal_widget_picker_title" msgid="1953369090475731663">"Sperrbildschirm-Widgets"</string> <string name="communal_widget_picker_description" msgid="490515450110487871">"Jeder kann Widgets auf deinem Sperrbildschirm sehen, auch bei gesperrtem Tablet."</string> - <!-- no translation found for accessibility_action_label_unselect_widget (1041811747619468698) --> - <skip /> + <string name="accessibility_action_label_unselect_widget" msgid="1041811747619468698">"Auswahl für Widget aufheben"</string> <string name="communal_widgets_disclaimer_title" msgid="1150954395585308868">"Sperrbildschirm-Widgets"</string> <string name="communal_widgets_disclaimer_text" msgid="1423545475160506349">"Wenn du eine App mit einem Widget öffnen möchtest, musst du deine Identität bestätigen. Beachte auch, dass jeder die Widgets sehen kann, auch wenn dein Tablet gesperrt ist. Einige Widgets sind möglicherweise nicht für den Sperrbildschirm vorgesehen, sodass es unsicher sein kann, sie hier hinzuzufügen."</string> <string name="communal_widgets_disclaimer_button" msgid="4423059765740780753">"Ok"</string> @@ -557,10 +565,8 @@ <string name="media_projection_action_text" msgid="3634906766918186440">"Jetzt starten"</string> <string name="empty_shade_text" msgid="8935967157319717412">"Keine Benachrichtigungen"</string> <string name="no_unseen_notif_text" msgid="395512586119868682">"Keine neuen Benachrichtigungen"</string> - <!-- no translation found for adaptive_notification_edu_hun_title (7790738150177329960) --> - <skip /> - <!-- no translation found for adaptive_notification_edu_hun_text (7743367744129536610) --> - <skip /> + <string name="adaptive_notification_edu_hun_title" msgid="7790738150177329960">"Verringern von Lautstärke und Vibration bei Benachrichtigungen ist an"</string> + <string name="adaptive_notification_edu_hun_text" msgid="7743367744129536610">"Wenn du in kurzer Zeit zu viele Benachrichtigungen erhältst, wird automatisch für bis zu 2 Minuten die Lautstärke des Geräts verringert und Benachrichtigungen werden reduziert."</string> <string name="go_to_adaptive_notification_settings" msgid="2423690125178298479">"Deaktivieren"</string> <string name="unlock_to_see_notif_text" msgid="7439033907167561227">"Für ältere Benachrichtigungen entsperren"</string> <string name="quick_settings_disclosure_parental_controls" msgid="2114102871438223600">"Dieses Gerät wird von deinen Eltern verwaltet"</string> @@ -1226,7 +1232,6 @@ <string name="accessibility_fingerprint_bouncer" msgid="7189102492498735519">"Authentifizierung erforderlich. Tippe dazu einfach auf den Fingerabdrucksensor."</string> <string name="ongoing_phone_call_content_description" msgid="5332334388483099947">"Aktiver Anruf"</string> <string name="mobile_data_settings_title" msgid="3955246641380064901">"Mobile Daten"</string> - <string name="preference_summary_default_combination" msgid="8453246369903749670">"<xliff:g id="STATE">%1$s</xliff:g>/<xliff:g id="NETWORKMODE">%2$s</xliff:g>"</string> <string name="mobile_data_connection_active" msgid="944490013299018227">"Verbunden"</string> <string name="mobile_data_temp_connection_active" msgid="4590222725908806824">"Vorübergehend verbunden"</string> <string name="mobile_data_poor_connection" msgid="819617772268371434">"Schwache Verbindung"</string> @@ -1380,7 +1385,10 @@ <string name="touchpad_tutorial_done_button" msgid="176168488821755503">"Fertig"</string> <string name="touchpad_tutorial_gesture_done" msgid="4784438360736821255">"Gut gemacht!"</string> <string name="touchpad_back_gesture_action_title" msgid="7199067250654332735">"Zurück"</string> - <string name="touchpad_back_gesture_guidance" msgid="4222430588599527272">"Wenn du zurückgehen möchtest, wische an einer beliebigen Stelle des Touchpads mit drei Fingern nach links oder rechts."</string> + <!-- no translation found for touchpad_back_gesture_guidance (6263750214998421587) --> + <skip /> + <!-- no translation found for touchpad_back_gesture_finished (5353616006999726249) --> + <skip /> <string name="touchpad_back_gesture_animation_content_description" msgid="2646107450922379918">"Touchpad mit drei Fingern, die sich nach links und rechts bewegen"</string> <string name="touchpad_back_gesture_screen_animation_content_description" msgid="4036267494237748710">"Bildschirm zeigt eine Animation der Touch-Geste „Zurück“"</string> <string name="keyboard_backlight_dialog_title" msgid="8273102932345564724">"Tastaturbeleuchtung"</string> @@ -1388,28 +1396,16 @@ <string name="home_controls_dream_label" msgid="6567105701292324257">"Smart-Home-Steuerung"</string> <string name="home_controls_dream_description" msgid="4644150952104035789">"Smart-Home-Steuerung als Bildschirmschoner nutzen"</string> <string name="volume_undo_action" msgid="5815519725211877114">"Rückgängig machen"</string> - <!-- no translation found for back_edu_toast_content (4530314597378982956) --> - <skip /> - <!-- no translation found for home_edu_toast_content (3381071147871955415) --> - <skip /> - <!-- no translation found for overview_edu_toast_content (5797030644017804518) --> - <skip /> - <!-- no translation found for all_apps_edu_toast_content (8807496014667211562) --> - <skip /> - <!-- no translation found for back_edu_notification_title (5624780717751357278) --> - <skip /> - <!-- no translation found for back_edu_notification_content (2497557451540954068) --> - <skip /> - <!-- no translation found for home_edu_notification_title (6097902076909654045) --> - <skip /> - <!-- no translation found for home_edu_notification_content (6631697734535766588) --> - <skip /> - <!-- no translation found for overview_edu_notification_title (1265824157319562406) --> - <skip /> - <!-- no translation found for overview_edu_notification_content (3578204677648432500) --> - <skip /> - <!-- no translation found for all_apps_edu_notification_title (372262997265569063) --> - <skip /> - <!-- no translation found for all_apps_edu_notification_content (3255070575694025585) --> - <skip /> + <string name="back_edu_toast_content" msgid="4530314597378982956">"Wenn du zurückgehen möchtest, wische auf dem Touchpad mit drei Fingern nach links oder rechts"</string> + <string name="home_edu_toast_content" msgid="3381071147871955415">"Wenn du den Startbildschirm aufrufen möchtest, wische auf dem Touchpad mit drei Fingern nach oben"</string> + <string name="overview_edu_toast_content" msgid="5797030644017804518">"Um zuletzt verwendete Apps aufzurufen, wische mit 3 Fingern nach oben und halte das Touchpad gedrückt"</string> + <string name="all_apps_edu_toast_content" msgid="8807496014667211562">"Wenn du alle deine Apps aufrufen möchtest, drücke auf der Tastatur die Aktionstaste"</string> + <string name="back_edu_notification_title" msgid="5624780717751357278">"Über das Touchpad zurückgehen"</string> + <string name="back_edu_notification_content" msgid="2497557451540954068">"Wische mit drei Fingern nach links oder rechts. Tippe für mehr Infos zu Touch-Gesten."</string> + <string name="home_edu_notification_title" msgid="6097902076909654045">"Über das Touchpad zum Startbildschirm zurückkehren"</string> + <string name="home_edu_notification_content" msgid="6631697734535766588">"Wische mit drei Fingern nach oben. Tippe für mehr Infos zu Touch-Gesten."</string> + <string name="overview_edu_notification_title" msgid="1265824157319562406">"Über das Touchpad zuletzt verwendete Apps aufrufen"</string> + <string name="overview_edu_notification_content" msgid="3578204677648432500">"Wische mit 3 Fingern nach oben und halte das Touchpad gedrückt. Tippe für mehr Infos zu Touch-Gesten."</string> + <string name="all_apps_edu_notification_title" msgid="372262997265569063">"Über die Tastatur alle Apps aufrufen"</string> + <string name="all_apps_edu_notification_content" msgid="3255070575694025585">"Du kannst jederzeit die Aktionstaste drücken. Tippe für mehr Infos zu Touch-Gesten."</string> </resources> diff --git a/packages/SystemUI/res/values-de/tiles_states_strings.xml b/packages/SystemUI/res/values-de/tiles_states_strings.xml index f27ac22aa925..0606cc79f2e9 100644 --- a/packages/SystemUI/res/values-de/tiles_states_strings.xml +++ b/packages/SystemUI/res/values-de/tiles_states_strings.xml @@ -56,11 +56,6 @@ <item msgid="5376619709702103243">"Aus"</item> <item msgid="4875147066469902392">"An"</item> </string-array> - <string-array name="tile_states_modes"> - <item msgid="7764936419245199023">"Nicht verfügbar"</item> - <item msgid="2004750556637773692">"Aus"</item> - <item msgid="8968530753931637871">"An"</item> - </string-array> <string-array name="tile_states_flashlight"> <item msgid="3465257127433353857">"Nicht verfügbar"</item> <item msgid="5044688398303285224">"Aus"</item> diff --git a/packages/SystemUI/res/values-el/strings.xml b/packages/SystemUI/res/values-el/strings.xml index 55c06d11e3a9..5025f6d91513 100644 --- a/packages/SystemUI/res/values-el/strings.xml +++ b/packages/SystemUI/res/values-el/strings.xml @@ -128,20 +128,20 @@ <string name="screenrecord_start_error" msgid="2200660692479682368">"Σφάλμα κατά την έναρξη της εγγραφής οθόνης"</string> <string name="screenrecord_stop_dialog_title" msgid="8716193661764511095">"Να διακοπεί η εγγραφή;"</string> <string name="screenrecord_stop_dialog_message" msgid="6262768207331626817">"Αυτή τη στιγμή εγγράφετε ολόκληρη την οθόνη σας"</string> - <string name="screenrecord_stop_dialog_message_specific_app" msgid="5995770227684523244">"Αυτή τη στιγμή εγγράφετε την <xliff:g id="APP_NAME">%1$s</xliff:g>"</string> + <string name="screenrecord_stop_dialog_message_specific_app" msgid="5995770227684523244">"Αυτή τη στιγμή εγγράφετε το <xliff:g id="APP_NAME">%1$s</xliff:g>"</string> <string name="screenrecord_stop_dialog_button" msgid="2883812564938194350">"Διακοπή εγγραφής"</string> <string name="share_to_app_chip_accessibility_label" msgid="4210256229976947065">"Γίνεται κοινοποίηση οθόνης"</string> <string name="share_to_app_stop_dialog_title" msgid="9212915050910250438">"Διακοπή κοινής χρήσης οθόνης;"</string> - <string name="share_to_app_stop_dialog_message_entire_screen_with_host_app" msgid="522823522115375414">"Αυτή τη στιγμή μοιράζεστε ολόκληρη την οθόνη σας με την <xliff:g id="HOST_APP_NAME">%1$s</xliff:g>"</string> + <string name="share_to_app_stop_dialog_message_entire_screen_with_host_app" msgid="522823522115375414">"Αυτή τη στιγμή μοιράζεστε ολόκληρη την οθόνη σας με το <xliff:g id="HOST_APP_NAME">%1$s</xliff:g>"</string> <string name="share_to_app_stop_dialog_message_entire_screen" msgid="5090115386271179270">"Αυτή τη στιγμή μοιράζεστε ολόκληρη την οθόνη σας με μια εφαρμογή"</string> - <string name="share_to_app_stop_dialog_message_single_app_specific" msgid="5923772039347985172">"Αυτή τη στιγμή μοιράζεστε την <xliff:g id="APP_BEING_SHARED_NAME">%1$s</xliff:g>"</string> + <string name="share_to_app_stop_dialog_message_single_app_specific" msgid="5923772039347985172">"Αυτή τη στιγμή μοιράζεστε το <xliff:g id="APP_BEING_SHARED_NAME">%1$s</xliff:g>"</string> <string name="share_to_app_stop_dialog_message_single_app_generic" msgid="6681016774654578261">"Αυτή τη στιγμή μοιράζεστε μια εφαρμογή"</string> <string name="share_to_app_stop_dialog_button" msgid="6334056916284230217">"Διακοπή κοινής χρήσης"</string> <string name="cast_screen_to_other_device_chip_accessibility_label" msgid="4687917476203009885">"Μετάδοση οθόνης"</string> <string name="cast_to_other_device_stop_dialog_title" msgid="7836517190930357326">"Τερματισμός μετάδοσης;"</string> <string name="cast_to_other_device_stop_dialog_message_entire_screen_with_device" msgid="1474703115926205251">"Αυτή τη στιγμή μεταδίδετε ολόκληρη την οθόνη σας στη <xliff:g id="DEVICE_NAME">%1$s</xliff:g>"</string> <string name="cast_to_other_device_stop_dialog_message_entire_screen" msgid="8419219169553867625">"Αυτή τη στιγμή μεταδίδετε ολόκληρη την οθόνη σας σε μια συσκευή σε κοντινή απόσταση"</string> - <string name="cast_to_other_device_stop_dialog_message_specific_app_with_device" msgid="2715934698604085519">"Αυτή τη στιγμή μεταδίδετε την <xliff:g id="APP_BEING_SHARED_NAME">%1$s</xliff:g> στη <xliff:g id="DEVICE_NAME">%2$s</xliff:g>"</string> + <string name="cast_to_other_device_stop_dialog_message_specific_app_with_device" msgid="2715934698604085519">"Αυτή τη στιγμή μεταδίδετε το <xliff:g id="APP_BEING_SHARED_NAME">%1$s</xliff:g> στο <xliff:g id="DEVICE_NAME">%2$s</xliff:g>"</string> <string name="cast_to_other_device_stop_dialog_message_specific_app" msgid="8616103075630934513">"Αυτή τη στιγμή μεταδίδετε την <xliff:g id="APP_BEING_SHARED_NAME">%1$s</xliff:g> σε μια συσκευή σε κοντινή απόσταση"</string> <string name="cast_to_other_device_stop_dialog_message_generic_with_device" msgid="9213582497852420203">"Αυτή τη στιγμή κάνετε μετάδοση στη <xliff:g id="DEVICE_NAME">%1$s</xliff:g>"</string> <string name="cast_to_other_device_stop_dialog_message_generic" msgid="4100272100480415076">"Αυτή τη στιγμή κάνετε μετάδοση σε μια συσκευή σε κοντινή απόσταση"</string> @@ -388,6 +388,9 @@ <string name="performance" msgid="6552785217174378320">"Απόδοση"</string> <string name="user_interface" msgid="3712869377953950887">"Διεπαφή χρήστη"</string> <string name="thermal" msgid="6758074791325414831">"Θερμικό"</string> + <string name="custom" msgid="3337456985275158299">"Προσαρμοσμένο"</string> + <string name="custom_trace_settings_dialog_title" msgid="2608570500144830554">"Ρυθμίσεις προσαρμοσμένου ίχνους"</string> + <string name="restore_default" msgid="5259420807486239755">"Επαναφορά προεπιλογής"</string> <string name="quick_settings_onehanded_label" msgid="2416537930246274991">"Λειτουργία ενός χεριού"</string> <string name="quick_settings_hearing_devices_label" msgid="7277170419679404129">"Συσκευές ακοής"</string> <string name="quick_settings_hearing_devices_connected" msgid="6519069502397037781">"Ενεργές"</string> @@ -429,9 +432,13 @@ <string name="zen_modes_dialog_title" msgid="4159138230418567383">"Λειτουργίες προτεραιότητας"</string> <string name="zen_modes_dialog_done" msgid="6654130880256438950">"Τέλος"</string> <string name="zen_modes_dialog_settings" msgid="2310248023728936697">"Ρυθμίσεις"</string> - <!-- no translation found for zen_mode_on (9085304934016242591) --> + <string name="zen_mode_on" msgid="9085304934016242591">"Ενεργό"</string> + <string name="zen_mode_off" msgid="1736604456618147306">"Ανενεργό"</string> + <!-- no translation found for zen_mode_set_up (7457957033034460064) --> <skip /> - <!-- no translation found for zen_mode_off (1736604456618147306) --> + <!-- no translation found for zen_mode_no_manual_invocation (1769975741344633672) --> + <skip /> + <!-- no translation found for zen_mode_active_modes (1625850411578488856) --> <skip /> <string name="zen_priority_introduction" msgid="3159291973383796646">"Δεν θα ενοχλείστε από ήχους και δονήσεις, παρά μόνο από ξυπνητήρια, υπενθυμίσεις, συμβάντα και καλούντες που έχετε καθορίσει. Θα εξακολουθείτε να ακούτε όλο το περιεχόμενο που επιλέγετε να αναπαραγάγετε, συμπεριλαμβανομένης της μουσικής, των βίντεο και των παιχνιδιών."</string> <string name="zen_alarms_introduction" msgid="3987266042682300470">"Δεν θα ενοχλείστε από ήχους και δονήσεις, παρά μόνο από ξυπνητήρια. Θα εξακολουθείτε να ακούτε όλο το περιεχόμενο που επιλέγετε να αναπαραγάγετε, συμπεριλαμβανομένης της μουσικής, των βίντεο και των παιχνιδιών."</string> @@ -471,6 +478,8 @@ <string name="keyguard_indication_charging_time_slowly" msgid="301936949731705417">"<xliff:g id="PERCENTAGE">%2$s</xliff:g> • Αργή φόρτιση • Πλήρης φόρτιση σε <xliff:g id="CHARGING_TIME_LEFT">%1$s</xliff:g>"</string> <string name="keyguard_indication_charging_time_dock" msgid="3149328898931741271">"<xliff:g id="PERCENTAGE">%2$s</xliff:g> • Φόρτιση • Πλήρης φόρτιση σε <xliff:g id="CHARGING_TIME_LEFT">%1$s</xliff:g>"</string> <string name="accessibility_action_open_communal_hub" msgid="3081702792413787849">"Γραφικά στοιχεία στην οθόνη κλειδώματος"</string> + <!-- no translation found for accessibility_announcement_communal_widget_added (6911593106099328271) --> + <skip /> <string name="communal_tutorial_indicator_text" msgid="4503010353591430123">"Σύρετε προς τα αριστερά για να ξεκινήσετε τον κοινόχρηστο οδηγό"</string> <string name="cta_tile_button_to_open_widget_editor" msgid="3871562362382963878">"Προσαρμογή"</string> <string name="cta_tile_button_to_dismiss" msgid="3377597875997861754">"Παράβλεψη"</string> @@ -499,8 +508,7 @@ <string name="accessibility_action_label_place_widget" msgid="1914197458644168978">"τοποθέτηση επιλεγμένου γραφικού στοιχείου"</string> <string name="communal_widget_picker_title" msgid="1953369090475731663">"Γραφικά στοιχεία οθόνης κλειδώματος"</string> <string name="communal_widget_picker_description" msgid="490515450110487871">"Όλοι μπορούν να δουν γραφικά στοιχεία στην οθόνη κλειδώματος, ακόμα και αν το tablet είναι κλειδωμένο."</string> - <!-- no translation found for accessibility_action_label_unselect_widget (1041811747619468698) --> - <skip /> + <string name="accessibility_action_label_unselect_widget" msgid="1041811747619468698">"αποεπιλογή γραφικού στοιχείου"</string> <string name="communal_widgets_disclaimer_title" msgid="1150954395585308868">"Γραφικά στοιχεία οθόνης κλειδώματος"</string> <string name="communal_widgets_disclaimer_text" msgid="1423545475160506349">"Για να ανοίξετε μια εφαρμογή χρησιμοποιώντας ένα γραφικό στοιχείο, θα πρέπει να επαληθεύσετε την ταυτότητά σας. Επίσης, λάβετε υπόψη ότι η προβολή τους είναι δυνατή από οποιονδήποτε, ακόμα και όταν το tablet σας είναι κλειδωμένο. Ορισμένα γραφικά στοιχεία μπορεί να μην προορίζονται για την οθόνη κλειδώματος και η προσθήκη τους εδώ ενδέχεται να μην είναι ασφαλής."</string> <string name="communal_widgets_disclaimer_button" msgid="4423059765740780753">"Το κατάλαβα"</string> @@ -557,10 +565,8 @@ <string name="media_projection_action_text" msgid="3634906766918186440">"Έναρξη τώρα"</string> <string name="empty_shade_text" msgid="8935967157319717412">"Δεν υπάρχουν ειδοποιήσεις"</string> <string name="no_unseen_notif_text" msgid="395512586119868682">"Δεν υπάρχουν νέες ειδοποιήσεις"</string> - <!-- no translation found for adaptive_notification_edu_hun_title (7790738150177329960) --> - <skip /> - <!-- no translation found for adaptive_notification_edu_hun_text (7743367744129536610) --> - <skip /> + <string name="adaptive_notification_edu_hun_title" msgid="7790738150177329960">"Η περίοδος cooldown ειδοποιήσεων είναι ενεργή"</string> + <string name="adaptive_notification_edu_hun_text" msgid="7743367744129536610">"Αυτόματη μείωση έντασης ήχου συσκευής και ειδοποιήσεων για έως 2 λεπτά όταν λαμβάνετε πολλές ειδοποιήσεις ταυτόχρονα."</string> <string name="go_to_adaptive_notification_settings" msgid="2423690125178298479">"Απενεργοποίηση"</string> <string name="unlock_to_see_notif_text" msgid="7439033907167561227">"Ξεκλειδώστε για εμφάνιση παλαιότ. ειδοπ."</string> <string name="quick_settings_disclosure_parental_controls" msgid="2114102871438223600">"Αυτή η συσκευή είναι διαχειριζόμενη από τον γονέα σου"</string> @@ -1226,7 +1232,6 @@ <string name="accessibility_fingerprint_bouncer" msgid="7189102492498735519">"Απαιτείται έλεγχος ταυτότητας. Αγγίξτε τον αισθητήρα δακτυλικών αποτυπωμάτων για έλεγχο ταυτότητας."</string> <string name="ongoing_phone_call_content_description" msgid="5332334388483099947">"Τηλεφωνική κλήση σε εξέλιξη"</string> <string name="mobile_data_settings_title" msgid="3955246641380064901">"Δεδομένα κινητής τηλεφωνίας"</string> - <string name="preference_summary_default_combination" msgid="8453246369903749670">"<xliff:g id="STATE">%1$s</xliff:g> / <xliff:g id="NETWORKMODE">%2$s</xliff:g>"</string> <string name="mobile_data_connection_active" msgid="944490013299018227">"Συνδέθηκε"</string> <string name="mobile_data_temp_connection_active" msgid="4590222725908806824">"Προσωρινή σύνδεση"</string> <string name="mobile_data_poor_connection" msgid="819617772268371434">"Ασθενής σύνδεση"</string> @@ -1380,7 +1385,10 @@ <string name="touchpad_tutorial_done_button" msgid="176168488821755503">"Τέλος"</string> <string name="touchpad_tutorial_gesture_done" msgid="4784438360736821255">"Μπράβο!"</string> <string name="touchpad_back_gesture_action_title" msgid="7199067250654332735">"Επιστροφή"</string> - <string name="touchpad_back_gesture_guidance" msgid="4222430588599527272">"Για επιστροφή, σύρετε προς τα αριστερά ή προς τα δεξιά χρησιμοποιώντας τρία δάχτυλα οπουδήποτε στην επιφάνεια αφής."</string> + <!-- no translation found for touchpad_back_gesture_guidance (6263750214998421587) --> + <skip /> + <!-- no translation found for touchpad_back_gesture_finished (5353616006999726249) --> + <skip /> <string name="touchpad_back_gesture_animation_content_description" msgid="2646107450922379918">"Επιφάνεια αφής στην οποία εμφανίζονται τρία δάχτυλα να κινούνται δεξιά και αριστερά"</string> <string name="touchpad_back_gesture_screen_animation_content_description" msgid="4036267494237748710">"Οθόνη συσκευής που εμφανίζει μια κινούμενη εικόνα σχετικά με την κίνηση επιστροφής"</string> <string name="keyboard_backlight_dialog_title" msgid="8273102932345564724">"Οπίσθιος φωτισμός πληκτρολογίου"</string> @@ -1388,28 +1396,16 @@ <string name="home_controls_dream_label" msgid="6567105701292324257">"Οικιακοί έλεγχοι"</string> <string name="home_controls_dream_description" msgid="4644150952104035789">"Γρήγ. πρόσβαση σε οικιακ. ελέγχους ως προφ. οθόνης"</string> <string name="volume_undo_action" msgid="5815519725211877114">"Αναίρεση"</string> - <!-- no translation found for back_edu_toast_content (4530314597378982956) --> - <skip /> - <!-- no translation found for home_edu_toast_content (3381071147871955415) --> - <skip /> - <!-- no translation found for overview_edu_toast_content (5797030644017804518) --> - <skip /> - <!-- no translation found for all_apps_edu_toast_content (8807496014667211562) --> - <skip /> - <!-- no translation found for back_edu_notification_title (5624780717751357278) --> - <skip /> - <!-- no translation found for back_edu_notification_content (2497557451540954068) --> - <skip /> - <!-- no translation found for home_edu_notification_title (6097902076909654045) --> - <skip /> - <!-- no translation found for home_edu_notification_content (6631697734535766588) --> - <skip /> - <!-- no translation found for overview_edu_notification_title (1265824157319562406) --> - <skip /> - <!-- no translation found for overview_edu_notification_content (3578204677648432500) --> - <skip /> - <!-- no translation found for all_apps_edu_notification_title (372262997265569063) --> - <skip /> - <!-- no translation found for all_apps_edu_notification_content (3255070575694025585) --> - <skip /> + <string name="back_edu_toast_content" msgid="4530314597378982956">"Για επιστροφή, σύρετε προς τα αριστερά ή τα δεξιά με τρία δάχτυλα στην επιφάνεια αφής"</string> + <string name="home_edu_toast_content" msgid="3381071147871955415">"Για μετάβαση στην αρχική οθόνη, σύρετε προς τα επάνω στην επιφάνεια αφής με τρία δάχτυλα"</string> + <string name="overview_edu_toast_content" msgid="5797030644017804518">"Για πρόσφατες εφαρμογές, σαρώστε προς τα πάνω με τρία δάχτυλα και κρατήστε τα στην επιφάνεια αφής"</string> + <string name="all_apps_edu_toast_content" msgid="8807496014667211562">"Για να δείτε όλες τις εφαρμογές, πιέστε το πλήκτρο ενέργειας στο πληκτρολόγιό σας"</string> + <string name="back_edu_notification_title" msgid="5624780717751357278">"Χρήση της επιφάνειας αφής για επιστροφή"</string> + <string name="back_edu_notification_content" msgid="2497557451540954068">"Σύρετε προς τα αριστερά ή τα δεξιά με τρία δάχτυλα. Πατήστε για να μάθετε περισσότερες κινήσεις."</string> + <string name="home_edu_notification_title" msgid="6097902076909654045">"Χρήση της επιφάνειας αφής για μετάβαση στην αρχική οθόνη"</string> + <string name="home_edu_notification_content" msgid="6631697734535766588">"Σύρετε προς τα πάνω με τρία δάχτυλα. Πατήστε για να μάθετε περισσότερες κινήσεις."</string> + <string name="overview_edu_notification_title" msgid="1265824157319562406">"Χρήση της επιφάνειας αφής για προβολή πρόσφατων εφαρμογών"</string> + <string name="overview_edu_notification_content" msgid="3578204677648432500">"Σύρετε προς τα πάνω με τρία δάχτυλα και μην τα σηκώσετε. Πατήστε για να δείτε περισσότερες κινήσεις."</string> + <string name="all_apps_edu_notification_title" msgid="372262997265569063">"Χρήση του πληκτρολογίου για προβολή όλων των εφαρμογών"</string> + <string name="all_apps_edu_notification_content" msgid="3255070575694025585">"Πιέστε το πλήκτρο ενέργειας ανά πάσα στιγμή. Πατήστε για να μάθετε περισσότερες κινήσεις."</string> </resources> diff --git a/packages/SystemUI/res/values-el/tiles_states_strings.xml b/packages/SystemUI/res/values-el/tiles_states_strings.xml index 9db5c8fdc636..d4545ffa6641 100644 --- a/packages/SystemUI/res/values-el/tiles_states_strings.xml +++ b/packages/SystemUI/res/values-el/tiles_states_strings.xml @@ -56,11 +56,6 @@ <item msgid="5376619709702103243">"Ανενεργό"</item> <item msgid="4875147066469902392">"Ενεργό"</item> </string-array> - <string-array name="tile_states_modes"> - <item msgid="7764936419245199023">"Μη διαθέσιμο"</item> - <item msgid="2004750556637773692">"Ανενεργό"</item> - <item msgid="8968530753931637871">"Ενεργό"</item> - </string-array> <string-array name="tile_states_flashlight"> <item msgid="3465257127433353857">"Μη διαθέσιμο"</item> <item msgid="5044688398303285224">"Ανενεργό"</item> diff --git a/packages/SystemUI/res/values-en-rAU/strings.xml b/packages/SystemUI/res/values-en-rAU/strings.xml index 23c3ff333821..f2ba7040713b 100644 --- a/packages/SystemUI/res/values-en-rAU/strings.xml +++ b/packages/SystemUI/res/values-en-rAU/strings.xml @@ -388,6 +388,9 @@ <string name="performance" msgid="6552785217174378320">"Performance"</string> <string name="user_interface" msgid="3712869377953950887">"User interface"</string> <string name="thermal" msgid="6758074791325414831">"Thermal"</string> + <string name="custom" msgid="3337456985275158299">"Custom"</string> + <string name="custom_trace_settings_dialog_title" msgid="2608570500144830554">"Custom trace settings"</string> + <string name="restore_default" msgid="5259420807486239755">"Restore default"</string> <string name="quick_settings_onehanded_label" msgid="2416537930246274991">"One-handed mode"</string> <string name="quick_settings_hearing_devices_label" msgid="7277170419679404129">"Hearing devices"</string> <string name="quick_settings_hearing_devices_connected" msgid="6519069502397037781">"Active"</string> @@ -429,9 +432,13 @@ <string name="zen_modes_dialog_title" msgid="4159138230418567383">"Priority modes"</string> <string name="zen_modes_dialog_done" msgid="6654130880256438950">"Done"</string> <string name="zen_modes_dialog_settings" msgid="2310248023728936697">"Settings"</string> - <!-- no translation found for zen_mode_on (9085304934016242591) --> + <string name="zen_mode_on" msgid="9085304934016242591">"On"</string> + <string name="zen_mode_off" msgid="1736604456618147306">"Off"</string> + <!-- no translation found for zen_mode_set_up (7457957033034460064) --> <skip /> - <!-- no translation found for zen_mode_off (1736604456618147306) --> + <!-- no translation found for zen_mode_no_manual_invocation (1769975741344633672) --> + <skip /> + <!-- no translation found for zen_mode_active_modes (1625850411578488856) --> <skip /> <string name="zen_priority_introduction" msgid="3159291973383796646">"You won\'t be disturbed by sounds and vibrations, except from alarms, reminders, events and callers you specify. You\'ll still hear anything you choose to play including music, videos and games."</string> <string name="zen_alarms_introduction" msgid="3987266042682300470">"You won\'t be disturbed by sounds and vibrations, except from alarms. You\'ll still hear anything you choose to play including music, videos and games."</string> @@ -471,6 +478,8 @@ <string name="keyguard_indication_charging_time_slowly" msgid="301936949731705417">"<xliff:g id="PERCENTAGE">%2$s</xliff:g> • Charging slowly • Full in <xliff:g id="CHARGING_TIME_LEFT">%1$s</xliff:g>"</string> <string name="keyguard_indication_charging_time_dock" msgid="3149328898931741271">"<xliff:g id="PERCENTAGE">%2$s</xliff:g> • Charging • Full in <xliff:g id="CHARGING_TIME_LEFT">%1$s</xliff:g>"</string> <string name="accessibility_action_open_communal_hub" msgid="3081702792413787849">"Widgets on lock screen"</string> + <!-- no translation found for accessibility_announcement_communal_widget_added (6911593106099328271) --> + <skip /> <string name="communal_tutorial_indicator_text" msgid="4503010353591430123">"Swipe left to start the communal tutorial"</string> <string name="cta_tile_button_to_open_widget_editor" msgid="3871562362382963878">"Customise"</string> <string name="cta_tile_button_to_dismiss" msgid="3377597875997861754">"Dismiss"</string> @@ -499,8 +508,7 @@ <string name="accessibility_action_label_place_widget" msgid="1914197458644168978">"place selected widget"</string> <string name="communal_widget_picker_title" msgid="1953369090475731663">"Lock screen widgets"</string> <string name="communal_widget_picker_description" msgid="490515450110487871">"Anyone can view widgets on your lock screen, even if your tablet\'s locked."</string> - <!-- no translation found for accessibility_action_label_unselect_widget (1041811747619468698) --> - <skip /> + <string name="accessibility_action_label_unselect_widget" msgid="1041811747619468698">"unselect widget"</string> <string name="communal_widgets_disclaimer_title" msgid="1150954395585308868">"Lock screen widgets"</string> <string name="communal_widgets_disclaimer_text" msgid="1423545475160506349">"To open an app using a widget, you\'ll need to verify that it\'s you. Also, bear in mind that anyone can view them, even when your tablet\'s locked. Some widgets may not have been intended for your lock screen and may be unsafe to add here."</string> <string name="communal_widgets_disclaimer_button" msgid="4423059765740780753">"Got it"</string> @@ -557,10 +565,8 @@ <string name="media_projection_action_text" msgid="3634906766918186440">"Start now"</string> <string name="empty_shade_text" msgid="8935967157319717412">"No notifications"</string> <string name="no_unseen_notif_text" msgid="395512586119868682">"No new notifications"</string> - <!-- no translation found for adaptive_notification_edu_hun_title (7790738150177329960) --> - <skip /> - <!-- no translation found for adaptive_notification_edu_hun_text (7743367744129536610) --> - <skip /> + <string name="adaptive_notification_edu_hun_title" msgid="7790738150177329960">"Notification cooldown is on"</string> + <string name="adaptive_notification_edu_hun_text" msgid="7743367744129536610">"Your device volume and alerts are reduced automatically for up to 2 minutes when you get too many notifications at once."</string> <string name="go_to_adaptive_notification_settings" msgid="2423690125178298479">"Turn off"</string> <string name="unlock_to_see_notif_text" msgid="7439033907167561227">"Unlock to see older notifications"</string> <string name="quick_settings_disclosure_parental_controls" msgid="2114102871438223600">"This device is managed by your parent"</string> @@ -1226,7 +1232,6 @@ <string name="accessibility_fingerprint_bouncer" msgid="7189102492498735519">"Authentication required. Touch the fingerprint sensor to authenticate."</string> <string name="ongoing_phone_call_content_description" msgid="5332334388483099947">"Ongoing phone call"</string> <string name="mobile_data_settings_title" msgid="3955246641380064901">"Mobile data"</string> - <string name="preference_summary_default_combination" msgid="8453246369903749670">"<xliff:g id="STATE">%1$s</xliff:g>/<xliff:g id="NETWORKMODE">%2$s</xliff:g>"</string> <string name="mobile_data_connection_active" msgid="944490013299018227">"Connected"</string> <string name="mobile_data_temp_connection_active" msgid="4590222725908806824">"Temporarily connected"</string> <string name="mobile_data_poor_connection" msgid="819617772268371434">"Poor connection"</string> @@ -1380,7 +1385,10 @@ <string name="touchpad_tutorial_done_button" msgid="176168488821755503">"Done"</string> <string name="touchpad_tutorial_gesture_done" msgid="4784438360736821255">"Great work!"</string> <string name="touchpad_back_gesture_action_title" msgid="7199067250654332735">"Go back"</string> - <string name="touchpad_back_gesture_guidance" msgid="4222430588599527272">"To go back, swipe left or right using 3 fingers anywhere on the touchpad."</string> + <!-- no translation found for touchpad_back_gesture_guidance (6263750214998421587) --> + <skip /> + <!-- no translation found for touchpad_back_gesture_finished (5353616006999726249) --> + <skip /> <string name="touchpad_back_gesture_animation_content_description" msgid="2646107450922379918">"Touchpad showing 3 fingers moving right and left"</string> <string name="touchpad_back_gesture_screen_animation_content_description" msgid="4036267494237748710">"Device screen showing animation for back gesture"</string> <string name="keyboard_backlight_dialog_title" msgid="8273102932345564724">"Keyboard backlight"</string> @@ -1388,28 +1396,16 @@ <string name="home_controls_dream_label" msgid="6567105701292324257">"Home controls"</string> <string name="home_controls_dream_description" msgid="4644150952104035789">"Quickly access your home controls as a screensaver"</string> <string name="volume_undo_action" msgid="5815519725211877114">"Undo"</string> - <!-- no translation found for back_edu_toast_content (4530314597378982956) --> - <skip /> - <!-- no translation found for home_edu_toast_content (3381071147871955415) --> - <skip /> - <!-- no translation found for overview_edu_toast_content (5797030644017804518) --> - <skip /> - <!-- no translation found for all_apps_edu_toast_content (8807496014667211562) --> - <skip /> - <!-- no translation found for back_edu_notification_title (5624780717751357278) --> - <skip /> - <!-- no translation found for back_edu_notification_content (2497557451540954068) --> - <skip /> - <!-- no translation found for home_edu_notification_title (6097902076909654045) --> - <skip /> - <!-- no translation found for home_edu_notification_content (6631697734535766588) --> - <skip /> - <!-- no translation found for overview_edu_notification_title (1265824157319562406) --> - <skip /> - <!-- no translation found for overview_edu_notification_content (3578204677648432500) --> - <skip /> - <!-- no translation found for all_apps_edu_notification_title (372262997265569063) --> - <skip /> - <!-- no translation found for all_apps_edu_notification_content (3255070575694025585) --> - <skip /> + <string name="back_edu_toast_content" msgid="4530314597378982956">"To go back, swipe left or right with three fingers on the touchpad"</string> + <string name="home_edu_toast_content" msgid="3381071147871955415">"To go home, swipe up with three fingers on the touchpad"</string> + <string name="overview_edu_toast_content" msgid="5797030644017804518">"To view recent apps, swipe up and hold with three fingers on the touchpad"</string> + <string name="all_apps_edu_toast_content" msgid="8807496014667211562">"To view all your apps, press the action key on your keyboard"</string> + <string name="back_edu_notification_title" msgid="5624780717751357278">"Use your touchpad to go back"</string> + <string name="back_edu_notification_content" msgid="2497557451540954068">"Swipe left or right using three fingers. Tap to learn more gestures."</string> + <string name="home_edu_notification_title" msgid="6097902076909654045">"Use your touchpad to go home"</string> + <string name="home_edu_notification_content" msgid="6631697734535766588">"Swipe up using three fingers. Tap to learn more gestures."</string> + <string name="overview_edu_notification_title" msgid="1265824157319562406">"Use your touchpad to view recent apps"</string> + <string name="overview_edu_notification_content" msgid="3578204677648432500">"Swipe up and hold using three fingers. Tap to learn more gestures."</string> + <string name="all_apps_edu_notification_title" msgid="372262997265569063">"Use your keyboard to view all apps"</string> + <string name="all_apps_edu_notification_content" msgid="3255070575694025585">"Press the action key at any time. Tap to learn more gestures."</string> </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 0658ce58e60f..39dd7c84b13e 100644 --- a/packages/SystemUI/res/values-en-rAU/tiles_states_strings.xml +++ b/packages/SystemUI/res/values-en-rAU/tiles_states_strings.xml @@ -56,11 +56,6 @@ <item msgid="5376619709702103243">"Off"</item> <item msgid="4875147066469902392">"On"</item> </string-array> - <string-array name="tile_states_modes"> - <item msgid="7764936419245199023">"Unavailable"</item> - <item msgid="2004750556637773692">"Off"</item> - <item msgid="8968530753931637871">"On"</item> - </string-array> <string-array name="tile_states_flashlight"> <item msgid="3465257127433353857">"Unavailable"</item> <item msgid="5044688398303285224">"Off"</item> diff --git a/packages/SystemUI/res/values-en-rCA/strings.xml b/packages/SystemUI/res/values-en-rCA/strings.xml index 8a582cb83cbb..5680cb7ccd04 100644 --- a/packages/SystemUI/res/values-en-rCA/strings.xml +++ b/packages/SystemUI/res/values-en-rCA/strings.xml @@ -388,6 +388,9 @@ <string name="performance" msgid="6552785217174378320">"Performance"</string> <string name="user_interface" msgid="3712869377953950887">"User Interface"</string> <string name="thermal" msgid="6758074791325414831">"Thermal"</string> + <string name="custom" msgid="3337456985275158299">"Custom"</string> + <string name="custom_trace_settings_dialog_title" msgid="2608570500144830554">"Custom Trace Settings"</string> + <string name="restore_default" msgid="5259420807486239755">"Restore Default"</string> <string name="quick_settings_onehanded_label" msgid="2416537930246274991">"One-handed mode"</string> <string name="quick_settings_hearing_devices_label" msgid="7277170419679404129">"Hearing devices"</string> <string name="quick_settings_hearing_devices_connected" msgid="6519069502397037781">"Active"</string> @@ -431,6 +434,9 @@ <string name="zen_modes_dialog_settings" msgid="2310248023728936697">"Settings"</string> <string name="zen_mode_on" msgid="9085304934016242591">"On"</string> <string name="zen_mode_off" msgid="1736604456618147306">"Off"</string> + <string name="zen_mode_set_up" msgid="7457957033034460064">"Set up"</string> + <string name="zen_mode_no_manual_invocation" msgid="1769975741344633672">"Manage in settings"</string> + <string name="zen_mode_active_modes" msgid="1625850411578488856">"{count,plural, =0{No active modes}=1{{mode} is active}other{# modes are active}}"</string> <string name="zen_priority_introduction" msgid="3159291973383796646">"You won\'t be disturbed by sounds and vibrations, except from alarms, reminders, events, and callers you specify. You\'ll still hear anything you choose to play including music, videos, and games."</string> <string name="zen_alarms_introduction" msgid="3987266042682300470">"You won\'t be disturbed by sounds and vibrations, except from alarms. You\'ll still hear anything you choose to play including music, videos, and games."</string> <string name="zen_priority_customize_button" msgid="4119213187257195047">"Customize"</string> @@ -469,6 +475,7 @@ <string name="keyguard_indication_charging_time_slowly" msgid="301936949731705417">"<xliff:g id="PERCENTAGE">%2$s</xliff:g> • Charging slowly • Full in <xliff:g id="CHARGING_TIME_LEFT">%1$s</xliff:g>"</string> <string name="keyguard_indication_charging_time_dock" msgid="3149328898931741271">"<xliff:g id="PERCENTAGE">%2$s</xliff:g> • Charging • Full in <xliff:g id="CHARGING_TIME_LEFT">%1$s</xliff:g>"</string> <string name="accessibility_action_open_communal_hub" msgid="3081702792413787849">"Widgets on lock screen"</string> + <string name="accessibility_announcement_communal_widget_added" msgid="6911593106099328271">"<xliff:g id="WIDGET_NAME">%1$s</xliff:g> widget added to lock screen"</string> <string name="communal_tutorial_indicator_text" msgid="4503010353591430123">"Swipe left to start the communal tutorial"</string> <string name="cta_tile_button_to_open_widget_editor" msgid="3871562362382963878">"Customize"</string> <string name="cta_tile_button_to_dismiss" msgid="3377597875997861754">"Dismiss"</string> @@ -1221,7 +1228,6 @@ <string name="accessibility_fingerprint_bouncer" msgid="7189102492498735519">"Authentication required. Touch the fingerprint sensor to authenticate."</string> <string name="ongoing_phone_call_content_description" msgid="5332334388483099947">"Ongoing phone call"</string> <string name="mobile_data_settings_title" msgid="3955246641380064901">"Mobile data"</string> - <string name="preference_summary_default_combination" msgid="8453246369903749670">"<xliff:g id="STATE">%1$s</xliff:g> / <xliff:g id="NETWORKMODE">%2$s</xliff:g>"</string> <string name="mobile_data_connection_active" msgid="944490013299018227">"Connected"</string> <string name="mobile_data_temp_connection_active" msgid="4590222725908806824">"Temporarily connected"</string> <string name="mobile_data_poor_connection" msgid="819617772268371434">"Poor connection"</string> @@ -1375,7 +1381,10 @@ <string name="touchpad_tutorial_done_button" msgid="176168488821755503">"Done"</string> <string name="touchpad_tutorial_gesture_done" msgid="4784438360736821255">"Great job!"</string> <string name="touchpad_back_gesture_action_title" msgid="7199067250654332735">"Go back"</string> - <string name="touchpad_back_gesture_guidance" msgid="4222430588599527272">"To go back, swipe left or right using three fingers anywhere on the touchpad."</string> + <!-- no translation found for touchpad_back_gesture_guidance (6263750214998421587) --> + <skip /> + <!-- no translation found for touchpad_back_gesture_finished (5353616006999726249) --> + <skip /> <string name="touchpad_back_gesture_animation_content_description" msgid="2646107450922379918">"Touchpad showing three fingers moving right and left"</string> <string name="touchpad_back_gesture_screen_animation_content_description" msgid="4036267494237748710">"Device screen showing animation for back gesture"</string> <string name="keyboard_backlight_dialog_title" msgid="8273102932345564724">"Keyboard backlight"</string> diff --git a/packages/SystemUI/res/values-en-rCA/tiles_states_strings.xml b/packages/SystemUI/res/values-en-rCA/tiles_states_strings.xml index 0658ce58e60f..39dd7c84b13e 100644 --- a/packages/SystemUI/res/values-en-rCA/tiles_states_strings.xml +++ b/packages/SystemUI/res/values-en-rCA/tiles_states_strings.xml @@ -56,11 +56,6 @@ <item msgid="5376619709702103243">"Off"</item> <item msgid="4875147066469902392">"On"</item> </string-array> - <string-array name="tile_states_modes"> - <item msgid="7764936419245199023">"Unavailable"</item> - <item msgid="2004750556637773692">"Off"</item> - <item msgid="8968530753931637871">"On"</item> - </string-array> <string-array name="tile_states_flashlight"> <item msgid="3465257127433353857">"Unavailable"</item> <item msgid="5044688398303285224">"Off"</item> diff --git a/packages/SystemUI/res/values-en-rGB/strings.xml b/packages/SystemUI/res/values-en-rGB/strings.xml index 23c3ff333821..f2ba7040713b 100644 --- a/packages/SystemUI/res/values-en-rGB/strings.xml +++ b/packages/SystemUI/res/values-en-rGB/strings.xml @@ -388,6 +388,9 @@ <string name="performance" msgid="6552785217174378320">"Performance"</string> <string name="user_interface" msgid="3712869377953950887">"User interface"</string> <string name="thermal" msgid="6758074791325414831">"Thermal"</string> + <string name="custom" msgid="3337456985275158299">"Custom"</string> + <string name="custom_trace_settings_dialog_title" msgid="2608570500144830554">"Custom trace settings"</string> + <string name="restore_default" msgid="5259420807486239755">"Restore default"</string> <string name="quick_settings_onehanded_label" msgid="2416537930246274991">"One-handed mode"</string> <string name="quick_settings_hearing_devices_label" msgid="7277170419679404129">"Hearing devices"</string> <string name="quick_settings_hearing_devices_connected" msgid="6519069502397037781">"Active"</string> @@ -429,9 +432,13 @@ <string name="zen_modes_dialog_title" msgid="4159138230418567383">"Priority modes"</string> <string name="zen_modes_dialog_done" msgid="6654130880256438950">"Done"</string> <string name="zen_modes_dialog_settings" msgid="2310248023728936697">"Settings"</string> - <!-- no translation found for zen_mode_on (9085304934016242591) --> + <string name="zen_mode_on" msgid="9085304934016242591">"On"</string> + <string name="zen_mode_off" msgid="1736604456618147306">"Off"</string> + <!-- no translation found for zen_mode_set_up (7457957033034460064) --> <skip /> - <!-- no translation found for zen_mode_off (1736604456618147306) --> + <!-- no translation found for zen_mode_no_manual_invocation (1769975741344633672) --> + <skip /> + <!-- no translation found for zen_mode_active_modes (1625850411578488856) --> <skip /> <string name="zen_priority_introduction" msgid="3159291973383796646">"You won\'t be disturbed by sounds and vibrations, except from alarms, reminders, events and callers you specify. You\'ll still hear anything you choose to play including music, videos and games."</string> <string name="zen_alarms_introduction" msgid="3987266042682300470">"You won\'t be disturbed by sounds and vibrations, except from alarms. You\'ll still hear anything you choose to play including music, videos and games."</string> @@ -471,6 +478,8 @@ <string name="keyguard_indication_charging_time_slowly" msgid="301936949731705417">"<xliff:g id="PERCENTAGE">%2$s</xliff:g> • Charging slowly • Full in <xliff:g id="CHARGING_TIME_LEFT">%1$s</xliff:g>"</string> <string name="keyguard_indication_charging_time_dock" msgid="3149328898931741271">"<xliff:g id="PERCENTAGE">%2$s</xliff:g> • Charging • Full in <xliff:g id="CHARGING_TIME_LEFT">%1$s</xliff:g>"</string> <string name="accessibility_action_open_communal_hub" msgid="3081702792413787849">"Widgets on lock screen"</string> + <!-- no translation found for accessibility_announcement_communal_widget_added (6911593106099328271) --> + <skip /> <string name="communal_tutorial_indicator_text" msgid="4503010353591430123">"Swipe left to start the communal tutorial"</string> <string name="cta_tile_button_to_open_widget_editor" msgid="3871562362382963878">"Customise"</string> <string name="cta_tile_button_to_dismiss" msgid="3377597875997861754">"Dismiss"</string> @@ -499,8 +508,7 @@ <string name="accessibility_action_label_place_widget" msgid="1914197458644168978">"place selected widget"</string> <string name="communal_widget_picker_title" msgid="1953369090475731663">"Lock screen widgets"</string> <string name="communal_widget_picker_description" msgid="490515450110487871">"Anyone can view widgets on your lock screen, even if your tablet\'s locked."</string> - <!-- no translation found for accessibility_action_label_unselect_widget (1041811747619468698) --> - <skip /> + <string name="accessibility_action_label_unselect_widget" msgid="1041811747619468698">"unselect widget"</string> <string name="communal_widgets_disclaimer_title" msgid="1150954395585308868">"Lock screen widgets"</string> <string name="communal_widgets_disclaimer_text" msgid="1423545475160506349">"To open an app using a widget, you\'ll need to verify that it\'s you. Also, bear in mind that anyone can view them, even when your tablet\'s locked. Some widgets may not have been intended for your lock screen and may be unsafe to add here."</string> <string name="communal_widgets_disclaimer_button" msgid="4423059765740780753">"Got it"</string> @@ -557,10 +565,8 @@ <string name="media_projection_action_text" msgid="3634906766918186440">"Start now"</string> <string name="empty_shade_text" msgid="8935967157319717412">"No notifications"</string> <string name="no_unseen_notif_text" msgid="395512586119868682">"No new notifications"</string> - <!-- no translation found for adaptive_notification_edu_hun_title (7790738150177329960) --> - <skip /> - <!-- no translation found for adaptive_notification_edu_hun_text (7743367744129536610) --> - <skip /> + <string name="adaptive_notification_edu_hun_title" msgid="7790738150177329960">"Notification cooldown is on"</string> + <string name="adaptive_notification_edu_hun_text" msgid="7743367744129536610">"Your device volume and alerts are reduced automatically for up to 2 minutes when you get too many notifications at once."</string> <string name="go_to_adaptive_notification_settings" msgid="2423690125178298479">"Turn off"</string> <string name="unlock_to_see_notif_text" msgid="7439033907167561227">"Unlock to see older notifications"</string> <string name="quick_settings_disclosure_parental_controls" msgid="2114102871438223600">"This device is managed by your parent"</string> @@ -1226,7 +1232,6 @@ <string name="accessibility_fingerprint_bouncer" msgid="7189102492498735519">"Authentication required. Touch the fingerprint sensor to authenticate."</string> <string name="ongoing_phone_call_content_description" msgid="5332334388483099947">"Ongoing phone call"</string> <string name="mobile_data_settings_title" msgid="3955246641380064901">"Mobile data"</string> - <string name="preference_summary_default_combination" msgid="8453246369903749670">"<xliff:g id="STATE">%1$s</xliff:g>/<xliff:g id="NETWORKMODE">%2$s</xliff:g>"</string> <string name="mobile_data_connection_active" msgid="944490013299018227">"Connected"</string> <string name="mobile_data_temp_connection_active" msgid="4590222725908806824">"Temporarily connected"</string> <string name="mobile_data_poor_connection" msgid="819617772268371434">"Poor connection"</string> @@ -1380,7 +1385,10 @@ <string name="touchpad_tutorial_done_button" msgid="176168488821755503">"Done"</string> <string name="touchpad_tutorial_gesture_done" msgid="4784438360736821255">"Great work!"</string> <string name="touchpad_back_gesture_action_title" msgid="7199067250654332735">"Go back"</string> - <string name="touchpad_back_gesture_guidance" msgid="4222430588599527272">"To go back, swipe left or right using 3 fingers anywhere on the touchpad."</string> + <!-- no translation found for touchpad_back_gesture_guidance (6263750214998421587) --> + <skip /> + <!-- no translation found for touchpad_back_gesture_finished (5353616006999726249) --> + <skip /> <string name="touchpad_back_gesture_animation_content_description" msgid="2646107450922379918">"Touchpad showing 3 fingers moving right and left"</string> <string name="touchpad_back_gesture_screen_animation_content_description" msgid="4036267494237748710">"Device screen showing animation for back gesture"</string> <string name="keyboard_backlight_dialog_title" msgid="8273102932345564724">"Keyboard backlight"</string> @@ -1388,28 +1396,16 @@ <string name="home_controls_dream_label" msgid="6567105701292324257">"Home controls"</string> <string name="home_controls_dream_description" msgid="4644150952104035789">"Quickly access your home controls as a screensaver"</string> <string name="volume_undo_action" msgid="5815519725211877114">"Undo"</string> - <!-- no translation found for back_edu_toast_content (4530314597378982956) --> - <skip /> - <!-- no translation found for home_edu_toast_content (3381071147871955415) --> - <skip /> - <!-- no translation found for overview_edu_toast_content (5797030644017804518) --> - <skip /> - <!-- no translation found for all_apps_edu_toast_content (8807496014667211562) --> - <skip /> - <!-- no translation found for back_edu_notification_title (5624780717751357278) --> - <skip /> - <!-- no translation found for back_edu_notification_content (2497557451540954068) --> - <skip /> - <!-- no translation found for home_edu_notification_title (6097902076909654045) --> - <skip /> - <!-- no translation found for home_edu_notification_content (6631697734535766588) --> - <skip /> - <!-- no translation found for overview_edu_notification_title (1265824157319562406) --> - <skip /> - <!-- no translation found for overview_edu_notification_content (3578204677648432500) --> - <skip /> - <!-- no translation found for all_apps_edu_notification_title (372262997265569063) --> - <skip /> - <!-- no translation found for all_apps_edu_notification_content (3255070575694025585) --> - <skip /> + <string name="back_edu_toast_content" msgid="4530314597378982956">"To go back, swipe left or right with three fingers on the touchpad"</string> + <string name="home_edu_toast_content" msgid="3381071147871955415">"To go home, swipe up with three fingers on the touchpad"</string> + <string name="overview_edu_toast_content" msgid="5797030644017804518">"To view recent apps, swipe up and hold with three fingers on the touchpad"</string> + <string name="all_apps_edu_toast_content" msgid="8807496014667211562">"To view all your apps, press the action key on your keyboard"</string> + <string name="back_edu_notification_title" msgid="5624780717751357278">"Use your touchpad to go back"</string> + <string name="back_edu_notification_content" msgid="2497557451540954068">"Swipe left or right using three fingers. Tap to learn more gestures."</string> + <string name="home_edu_notification_title" msgid="6097902076909654045">"Use your touchpad to go home"</string> + <string name="home_edu_notification_content" msgid="6631697734535766588">"Swipe up using three fingers. Tap to learn more gestures."</string> + <string name="overview_edu_notification_title" msgid="1265824157319562406">"Use your touchpad to view recent apps"</string> + <string name="overview_edu_notification_content" msgid="3578204677648432500">"Swipe up and hold using three fingers. Tap to learn more gestures."</string> + <string name="all_apps_edu_notification_title" msgid="372262997265569063">"Use your keyboard to view all apps"</string> + <string name="all_apps_edu_notification_content" msgid="3255070575694025585">"Press the action key at any time. Tap to learn more gestures."</string> </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 0658ce58e60f..39dd7c84b13e 100644 --- a/packages/SystemUI/res/values-en-rGB/tiles_states_strings.xml +++ b/packages/SystemUI/res/values-en-rGB/tiles_states_strings.xml @@ -56,11 +56,6 @@ <item msgid="5376619709702103243">"Off"</item> <item msgid="4875147066469902392">"On"</item> </string-array> - <string-array name="tile_states_modes"> - <item msgid="7764936419245199023">"Unavailable"</item> - <item msgid="2004750556637773692">"Off"</item> - <item msgid="8968530753931637871">"On"</item> - </string-array> <string-array name="tile_states_flashlight"> <item msgid="3465257127433353857">"Unavailable"</item> <item msgid="5044688398303285224">"Off"</item> diff --git a/packages/SystemUI/res/values-en-rIN/strings.xml b/packages/SystemUI/res/values-en-rIN/strings.xml index 23c3ff333821..f2ba7040713b 100644 --- a/packages/SystemUI/res/values-en-rIN/strings.xml +++ b/packages/SystemUI/res/values-en-rIN/strings.xml @@ -388,6 +388,9 @@ <string name="performance" msgid="6552785217174378320">"Performance"</string> <string name="user_interface" msgid="3712869377953950887">"User interface"</string> <string name="thermal" msgid="6758074791325414831">"Thermal"</string> + <string name="custom" msgid="3337456985275158299">"Custom"</string> + <string name="custom_trace_settings_dialog_title" msgid="2608570500144830554">"Custom trace settings"</string> + <string name="restore_default" msgid="5259420807486239755">"Restore default"</string> <string name="quick_settings_onehanded_label" msgid="2416537930246274991">"One-handed mode"</string> <string name="quick_settings_hearing_devices_label" msgid="7277170419679404129">"Hearing devices"</string> <string name="quick_settings_hearing_devices_connected" msgid="6519069502397037781">"Active"</string> @@ -429,9 +432,13 @@ <string name="zen_modes_dialog_title" msgid="4159138230418567383">"Priority modes"</string> <string name="zen_modes_dialog_done" msgid="6654130880256438950">"Done"</string> <string name="zen_modes_dialog_settings" msgid="2310248023728936697">"Settings"</string> - <!-- no translation found for zen_mode_on (9085304934016242591) --> + <string name="zen_mode_on" msgid="9085304934016242591">"On"</string> + <string name="zen_mode_off" msgid="1736604456618147306">"Off"</string> + <!-- no translation found for zen_mode_set_up (7457957033034460064) --> <skip /> - <!-- no translation found for zen_mode_off (1736604456618147306) --> + <!-- no translation found for zen_mode_no_manual_invocation (1769975741344633672) --> + <skip /> + <!-- no translation found for zen_mode_active_modes (1625850411578488856) --> <skip /> <string name="zen_priority_introduction" msgid="3159291973383796646">"You won\'t be disturbed by sounds and vibrations, except from alarms, reminders, events and callers you specify. You\'ll still hear anything you choose to play including music, videos and games."</string> <string name="zen_alarms_introduction" msgid="3987266042682300470">"You won\'t be disturbed by sounds and vibrations, except from alarms. You\'ll still hear anything you choose to play including music, videos and games."</string> @@ -471,6 +478,8 @@ <string name="keyguard_indication_charging_time_slowly" msgid="301936949731705417">"<xliff:g id="PERCENTAGE">%2$s</xliff:g> • Charging slowly • Full in <xliff:g id="CHARGING_TIME_LEFT">%1$s</xliff:g>"</string> <string name="keyguard_indication_charging_time_dock" msgid="3149328898931741271">"<xliff:g id="PERCENTAGE">%2$s</xliff:g> • Charging • Full in <xliff:g id="CHARGING_TIME_LEFT">%1$s</xliff:g>"</string> <string name="accessibility_action_open_communal_hub" msgid="3081702792413787849">"Widgets on lock screen"</string> + <!-- no translation found for accessibility_announcement_communal_widget_added (6911593106099328271) --> + <skip /> <string name="communal_tutorial_indicator_text" msgid="4503010353591430123">"Swipe left to start the communal tutorial"</string> <string name="cta_tile_button_to_open_widget_editor" msgid="3871562362382963878">"Customise"</string> <string name="cta_tile_button_to_dismiss" msgid="3377597875997861754">"Dismiss"</string> @@ -499,8 +508,7 @@ <string name="accessibility_action_label_place_widget" msgid="1914197458644168978">"place selected widget"</string> <string name="communal_widget_picker_title" msgid="1953369090475731663">"Lock screen widgets"</string> <string name="communal_widget_picker_description" msgid="490515450110487871">"Anyone can view widgets on your lock screen, even if your tablet\'s locked."</string> - <!-- no translation found for accessibility_action_label_unselect_widget (1041811747619468698) --> - <skip /> + <string name="accessibility_action_label_unselect_widget" msgid="1041811747619468698">"unselect widget"</string> <string name="communal_widgets_disclaimer_title" msgid="1150954395585308868">"Lock screen widgets"</string> <string name="communal_widgets_disclaimer_text" msgid="1423545475160506349">"To open an app using a widget, you\'ll need to verify that it\'s you. Also, bear in mind that anyone can view them, even when your tablet\'s locked. Some widgets may not have been intended for your lock screen and may be unsafe to add here."</string> <string name="communal_widgets_disclaimer_button" msgid="4423059765740780753">"Got it"</string> @@ -557,10 +565,8 @@ <string name="media_projection_action_text" msgid="3634906766918186440">"Start now"</string> <string name="empty_shade_text" msgid="8935967157319717412">"No notifications"</string> <string name="no_unseen_notif_text" msgid="395512586119868682">"No new notifications"</string> - <!-- no translation found for adaptive_notification_edu_hun_title (7790738150177329960) --> - <skip /> - <!-- no translation found for adaptive_notification_edu_hun_text (7743367744129536610) --> - <skip /> + <string name="adaptive_notification_edu_hun_title" msgid="7790738150177329960">"Notification cooldown is on"</string> + <string name="adaptive_notification_edu_hun_text" msgid="7743367744129536610">"Your device volume and alerts are reduced automatically for up to 2 minutes when you get too many notifications at once."</string> <string name="go_to_adaptive_notification_settings" msgid="2423690125178298479">"Turn off"</string> <string name="unlock_to_see_notif_text" msgid="7439033907167561227">"Unlock to see older notifications"</string> <string name="quick_settings_disclosure_parental_controls" msgid="2114102871438223600">"This device is managed by your parent"</string> @@ -1226,7 +1232,6 @@ <string name="accessibility_fingerprint_bouncer" msgid="7189102492498735519">"Authentication required. Touch the fingerprint sensor to authenticate."</string> <string name="ongoing_phone_call_content_description" msgid="5332334388483099947">"Ongoing phone call"</string> <string name="mobile_data_settings_title" msgid="3955246641380064901">"Mobile data"</string> - <string name="preference_summary_default_combination" msgid="8453246369903749670">"<xliff:g id="STATE">%1$s</xliff:g>/<xliff:g id="NETWORKMODE">%2$s</xliff:g>"</string> <string name="mobile_data_connection_active" msgid="944490013299018227">"Connected"</string> <string name="mobile_data_temp_connection_active" msgid="4590222725908806824">"Temporarily connected"</string> <string name="mobile_data_poor_connection" msgid="819617772268371434">"Poor connection"</string> @@ -1380,7 +1385,10 @@ <string name="touchpad_tutorial_done_button" msgid="176168488821755503">"Done"</string> <string name="touchpad_tutorial_gesture_done" msgid="4784438360736821255">"Great work!"</string> <string name="touchpad_back_gesture_action_title" msgid="7199067250654332735">"Go back"</string> - <string name="touchpad_back_gesture_guidance" msgid="4222430588599527272">"To go back, swipe left or right using 3 fingers anywhere on the touchpad."</string> + <!-- no translation found for touchpad_back_gesture_guidance (6263750214998421587) --> + <skip /> + <!-- no translation found for touchpad_back_gesture_finished (5353616006999726249) --> + <skip /> <string name="touchpad_back_gesture_animation_content_description" msgid="2646107450922379918">"Touchpad showing 3 fingers moving right and left"</string> <string name="touchpad_back_gesture_screen_animation_content_description" msgid="4036267494237748710">"Device screen showing animation for back gesture"</string> <string name="keyboard_backlight_dialog_title" msgid="8273102932345564724">"Keyboard backlight"</string> @@ -1388,28 +1396,16 @@ <string name="home_controls_dream_label" msgid="6567105701292324257">"Home controls"</string> <string name="home_controls_dream_description" msgid="4644150952104035789">"Quickly access your home controls as a screensaver"</string> <string name="volume_undo_action" msgid="5815519725211877114">"Undo"</string> - <!-- no translation found for back_edu_toast_content (4530314597378982956) --> - <skip /> - <!-- no translation found for home_edu_toast_content (3381071147871955415) --> - <skip /> - <!-- no translation found for overview_edu_toast_content (5797030644017804518) --> - <skip /> - <!-- no translation found for all_apps_edu_toast_content (8807496014667211562) --> - <skip /> - <!-- no translation found for back_edu_notification_title (5624780717751357278) --> - <skip /> - <!-- no translation found for back_edu_notification_content (2497557451540954068) --> - <skip /> - <!-- no translation found for home_edu_notification_title (6097902076909654045) --> - <skip /> - <!-- no translation found for home_edu_notification_content (6631697734535766588) --> - <skip /> - <!-- no translation found for overview_edu_notification_title (1265824157319562406) --> - <skip /> - <!-- no translation found for overview_edu_notification_content (3578204677648432500) --> - <skip /> - <!-- no translation found for all_apps_edu_notification_title (372262997265569063) --> - <skip /> - <!-- no translation found for all_apps_edu_notification_content (3255070575694025585) --> - <skip /> + <string name="back_edu_toast_content" msgid="4530314597378982956">"To go back, swipe left or right with three fingers on the touchpad"</string> + <string name="home_edu_toast_content" msgid="3381071147871955415">"To go home, swipe up with three fingers on the touchpad"</string> + <string name="overview_edu_toast_content" msgid="5797030644017804518">"To view recent apps, swipe up and hold with three fingers on the touchpad"</string> + <string name="all_apps_edu_toast_content" msgid="8807496014667211562">"To view all your apps, press the action key on your keyboard"</string> + <string name="back_edu_notification_title" msgid="5624780717751357278">"Use your touchpad to go back"</string> + <string name="back_edu_notification_content" msgid="2497557451540954068">"Swipe left or right using three fingers. Tap to learn more gestures."</string> + <string name="home_edu_notification_title" msgid="6097902076909654045">"Use your touchpad to go home"</string> + <string name="home_edu_notification_content" msgid="6631697734535766588">"Swipe up using three fingers. Tap to learn more gestures."</string> + <string name="overview_edu_notification_title" msgid="1265824157319562406">"Use your touchpad to view recent apps"</string> + <string name="overview_edu_notification_content" msgid="3578204677648432500">"Swipe up and hold using three fingers. Tap to learn more gestures."</string> + <string name="all_apps_edu_notification_title" msgid="372262997265569063">"Use your keyboard to view all apps"</string> + <string name="all_apps_edu_notification_content" msgid="3255070575694025585">"Press the action key at any time. Tap to learn more gestures."</string> </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 0658ce58e60f..39dd7c84b13e 100644 --- a/packages/SystemUI/res/values-en-rIN/tiles_states_strings.xml +++ b/packages/SystemUI/res/values-en-rIN/tiles_states_strings.xml @@ -56,11 +56,6 @@ <item msgid="5376619709702103243">"Off"</item> <item msgid="4875147066469902392">"On"</item> </string-array> - <string-array name="tile_states_modes"> - <item msgid="7764936419245199023">"Unavailable"</item> - <item msgid="2004750556637773692">"Off"</item> - <item msgid="8968530753931637871">"On"</item> - </string-array> <string-array name="tile_states_flashlight"> <item msgid="3465257127433353857">"Unavailable"</item> <item msgid="5044688398303285224">"Off"</item> diff --git a/packages/SystemUI/res/values-en-rXC/strings.xml b/packages/SystemUI/res/values-en-rXC/strings.xml index 7ff790037472..f99ab9e919f7 100644 --- a/packages/SystemUI/res/values-en-rXC/strings.xml +++ b/packages/SystemUI/res/values-en-rXC/strings.xml @@ -388,6 +388,9 @@ <string name="performance" msgid="6552785217174378320">"Performance"</string> <string name="user_interface" msgid="3712869377953950887">"User Interface"</string> <string name="thermal" msgid="6758074791325414831">"Thermal"</string> + <string name="custom" msgid="3337456985275158299">"Custom"</string> + <string name="custom_trace_settings_dialog_title" msgid="2608570500144830554">"Custom Trace Settings"</string> + <string name="restore_default" msgid="5259420807486239755">"Restore Default"</string> <string name="quick_settings_onehanded_label" msgid="2416537930246274991">"One-handed mode"</string> <string name="quick_settings_hearing_devices_label" msgid="7277170419679404129">"Hearing devices"</string> <string name="quick_settings_hearing_devices_connected" msgid="6519069502397037781">"Active"</string> @@ -431,6 +434,9 @@ <string name="zen_modes_dialog_settings" msgid="2310248023728936697">"Settings"</string> <string name="zen_mode_on" msgid="9085304934016242591">"On"</string> <string name="zen_mode_off" msgid="1736604456618147306">"Off"</string> + <string name="zen_mode_set_up" msgid="7457957033034460064">"Set up"</string> + <string name="zen_mode_no_manual_invocation" msgid="1769975741344633672">"Manage in settings"</string> + <string name="zen_mode_active_modes" msgid="1625850411578488856">"{count,plural, =0{No active modes}=1{{mode} is active}other{# modes are active}}"</string> <string name="zen_priority_introduction" msgid="3159291973383796646">"You won\'t be disturbed by sounds and vibrations, except from alarms, reminders, events, and callers you specify. You\'ll still hear anything you choose to play including music, videos, and games."</string> <string name="zen_alarms_introduction" msgid="3987266042682300470">"You won\'t be disturbed by sounds and vibrations, except from alarms. You\'ll still hear anything you choose to play including music, videos, and games."</string> <string name="zen_priority_customize_button" msgid="4119213187257195047">"Customize"</string> @@ -469,6 +475,7 @@ <string name="keyguard_indication_charging_time_slowly" msgid="301936949731705417">"<xliff:g id="PERCENTAGE">%2$s</xliff:g> • Charging slowly • Full in <xliff:g id="CHARGING_TIME_LEFT">%1$s</xliff:g>"</string> <string name="keyguard_indication_charging_time_dock" msgid="3149328898931741271">"<xliff:g id="PERCENTAGE">%2$s</xliff:g> • Charging • Full in <xliff:g id="CHARGING_TIME_LEFT">%1$s</xliff:g>"</string> <string name="accessibility_action_open_communal_hub" msgid="3081702792413787849">"Widgets on lock screen"</string> + <string name="accessibility_announcement_communal_widget_added" msgid="6911593106099328271">"<xliff:g id="WIDGET_NAME">%1$s</xliff:g> widget added to lock screen"</string> <string name="communal_tutorial_indicator_text" msgid="4503010353591430123">"Swipe left to start the communal tutorial"</string> <string name="cta_tile_button_to_open_widget_editor" msgid="3871562362382963878">"Customize"</string> <string name="cta_tile_button_to_dismiss" msgid="3377597875997861754">"Dismiss"</string> @@ -1221,7 +1228,6 @@ <string name="accessibility_fingerprint_bouncer" msgid="7189102492498735519">"Authentication required. Touch the fingerprint sensor to authenticate."</string> <string name="ongoing_phone_call_content_description" msgid="5332334388483099947">"Ongoing phone call"</string> <string name="mobile_data_settings_title" msgid="3955246641380064901">"Mobile data"</string> - <string name="preference_summary_default_combination" msgid="8453246369903749670">"<xliff:g id="STATE">%1$s</xliff:g> / <xliff:g id="NETWORKMODE">%2$s</xliff:g>"</string> <string name="mobile_data_connection_active" msgid="944490013299018227">"Connected"</string> <string name="mobile_data_temp_connection_active" msgid="4590222725908806824">"Temporarily connected"</string> <string name="mobile_data_poor_connection" msgid="819617772268371434">"Poor connection"</string> @@ -1375,7 +1381,10 @@ <string name="touchpad_tutorial_done_button" msgid="176168488821755503">"Done"</string> <string name="touchpad_tutorial_gesture_done" msgid="4784438360736821255">"Great job!"</string> <string name="touchpad_back_gesture_action_title" msgid="7199067250654332735">"Go back"</string> - <string name="touchpad_back_gesture_guidance" msgid="4222430588599527272">"To go back, swipe left or right using three fingers anywhere on the touchpad."</string> + <!-- no translation found for touchpad_back_gesture_guidance (6263750214998421587) --> + <skip /> + <!-- no translation found for touchpad_back_gesture_finished (5353616006999726249) --> + <skip /> <string name="touchpad_back_gesture_animation_content_description" msgid="2646107450922379918">"Touchpad showing three fingers moving right and left"</string> <string name="touchpad_back_gesture_screen_animation_content_description" msgid="4036267494237748710">"Device screen showing animation for back gesture"</string> <string name="keyboard_backlight_dialog_title" msgid="8273102932345564724">"Keyboard backlight"</string> diff --git a/packages/SystemUI/res/values-en-rXC/tiles_states_strings.xml b/packages/SystemUI/res/values-en-rXC/tiles_states_strings.xml index a6a5fddbb8ef..35ab88b202de 100644 --- a/packages/SystemUI/res/values-en-rXC/tiles_states_strings.xml +++ b/packages/SystemUI/res/values-en-rXC/tiles_states_strings.xml @@ -56,11 +56,6 @@ <item msgid="5376619709702103243">"Off"</item> <item msgid="4875147066469902392">"On"</item> </string-array> - <string-array name="tile_states_modes"> - <item msgid="7764936419245199023">"Unavailable"</item> - <item msgid="2004750556637773692">"Off"</item> - <item msgid="8968530753931637871">"On"</item> - </string-array> <string-array name="tile_states_flashlight"> <item msgid="3465257127433353857">"Unavailable"</item> <item msgid="5044688398303285224">"Off"</item> diff --git a/packages/SystemUI/res/values-es-rUS/strings.xml b/packages/SystemUI/res/values-es-rUS/strings.xml index fcfd1f4057b2..31344fa7389a 100644 --- a/packages/SystemUI/res/values-es-rUS/strings.xml +++ b/packages/SystemUI/res/values-es-rUS/strings.xml @@ -129,7 +129,7 @@ <string name="screenrecord_stop_dialog_title" msgid="8716193661764511095">"¿Quieres detener la grabación?"</string> <string name="screenrecord_stop_dialog_message" msgid="6262768207331626817">"Actualmente, estás grabando toda la pantalla"</string> <string name="screenrecord_stop_dialog_message_specific_app" msgid="5995770227684523244">"Actualmente, estás grabando <xliff:g id="APP_NAME">%1$s</xliff:g>"</string> - <string name="screenrecord_stop_dialog_button" msgid="2883812564938194350">"Detener la grabación"</string> + <string name="screenrecord_stop_dialog_button" msgid="2883812564938194350">"Detener grabación"</string> <string name="share_to_app_chip_accessibility_label" msgid="4210256229976947065">"Compartiendo pantalla"</string> <string name="share_to_app_stop_dialog_title" msgid="9212915050910250438">"¿Quieres dejar de compartir la pantalla?"</string> <string name="share_to_app_stop_dialog_message_entire_screen_with_host_app" msgid="522823522115375414">"Actualmente, estás compartiendo toda la pantalla con <xliff:g id="HOST_APP_NAME">%1$s</xliff:g>"</string> @@ -388,6 +388,9 @@ <string name="performance" msgid="6552785217174378320">"Rendimiento"</string> <string name="user_interface" msgid="3712869377953950887">"Interfaz de usuario"</string> <string name="thermal" msgid="6758074791325414831">"Térmico"</string> + <string name="custom" msgid="3337456985275158299">"Personalizado"</string> + <string name="custom_trace_settings_dialog_title" msgid="2608570500144830554">"Configuración de rastreo personalizada"</string> + <string name="restore_default" msgid="5259420807486239755">"Restablecer configuración predeterminada"</string> <string name="quick_settings_onehanded_label" msgid="2416537930246274991">"Modo una mano"</string> <string name="quick_settings_hearing_devices_label" msgid="7277170419679404129">"Dispositivos auditivos"</string> <string name="quick_settings_hearing_devices_connected" msgid="6519069502397037781">"Activos"</string> @@ -429,9 +432,13 @@ <string name="zen_modes_dialog_title" msgid="4159138230418567383">"Modos de prioridad"</string> <string name="zen_modes_dialog_done" msgid="6654130880256438950">"Listo"</string> <string name="zen_modes_dialog_settings" msgid="2310248023728936697">"Configuración"</string> - <!-- no translation found for zen_mode_on (9085304934016242591) --> + <string name="zen_mode_on" msgid="9085304934016242591">"Activado"</string> + <string name="zen_mode_off" msgid="1736604456618147306">"Desactivado"</string> + <!-- no translation found for zen_mode_set_up (7457957033034460064) --> <skip /> - <!-- no translation found for zen_mode_off (1736604456618147306) --> + <!-- no translation found for zen_mode_no_manual_invocation (1769975741344633672) --> + <skip /> + <!-- no translation found for zen_mode_active_modes (1625850411578488856) --> <skip /> <string name="zen_priority_introduction" msgid="3159291973383796646">"No te molestarán los sonidos ni las vibraciones, excepto las alarmas, los recordatorios, los eventos y las llamadas de los emisores que especifiques. Podrás escuchar el contenido que reproduzcas, como música, videos y juegos."</string> <string name="zen_alarms_introduction" msgid="3987266042682300470">"No te molestarán los sonidos ni las vibraciones, excepto las alarmas. Podrás escuchar el contenido que reproduzcas, como música, videos y juegos."</string> @@ -471,6 +478,8 @@ <string name="keyguard_indication_charging_time_slowly" msgid="301936949731705417">"<xliff:g id="PERCENTAGE">%2$s</xliff:g> • Cargando lento • Se completará en <xliff:g id="CHARGING_TIME_LEFT">%1$s</xliff:g>"</string> <string name="keyguard_indication_charging_time_dock" msgid="3149328898931741271">"<xliff:g id="PERCENTAGE">%2$s</xliff:g> • Cargando • Se completará en <xliff:g id="CHARGING_TIME_LEFT">%1$s</xliff:g>"</string> <string name="accessibility_action_open_communal_hub" msgid="3081702792413787849">"Widgets en la pantalla de bloqueo"</string> + <!-- no translation found for accessibility_announcement_communal_widget_added (6911593106099328271) --> + <skip /> <string name="communal_tutorial_indicator_text" msgid="4503010353591430123">"Desliza el dedo a la izquierda para iniciar el instructivo comunal"</string> <string name="cta_tile_button_to_open_widget_editor" msgid="3871562362382963878">"Personalizar"</string> <string name="cta_tile_button_to_dismiss" msgid="3377597875997861754">"Descartar"</string> @@ -499,8 +508,7 @@ <string name="accessibility_action_label_place_widget" msgid="1914197458644168978">"colocar widget seleccionado"</string> <string name="communal_widget_picker_title" msgid="1953369090475731663">"Widgets en la pantalla de bloqueo"</string> <string name="communal_widget_picker_description" msgid="490515450110487871">"Los widgets de la pantalla de bloqueo podrán verse incluso si bloqueas la tablet."</string> - <!-- no translation found for accessibility_action_label_unselect_widget (1041811747619468698) --> - <skip /> + <string name="accessibility_action_label_unselect_widget" msgid="1041811747619468698">"anular la selección del widget"</string> <string name="communal_widgets_disclaimer_title" msgid="1150954395585308868">"Widgets en la pantalla de bloqueo"</string> <string name="communal_widgets_disclaimer_text" msgid="1423545475160506349">"Para abrir una app usando un widget, debes verificar tu identidad. Además, ten en cuenta que cualquier persona podrá verlo, incluso cuando la tablet esté bloqueada. Es posible que algunos widgets no se hayan diseñados para la pantalla de bloqueo y podría ser peligroso agregarlos allí."</string> <string name="communal_widgets_disclaimer_button" msgid="4423059765740780753">"Entendido"</string> @@ -557,10 +565,8 @@ <string name="media_projection_action_text" msgid="3634906766918186440">"Comenzar ahora"</string> <string name="empty_shade_text" msgid="8935967157319717412">"No hay notificaciones"</string> <string name="no_unseen_notif_text" msgid="395512586119868682">"No hay notificaciones nuevas"</string> - <!-- no translation found for adaptive_notification_edu_hun_title (7790738150177329960) --> - <skip /> - <!-- no translation found for adaptive_notification_edu_hun_text (7743367744129536610) --> - <skip /> + <string name="adaptive_notification_edu_hun_title" msgid="7790738150177329960">"Reducción de sonido de notificaciones activada"</string> + <string name="adaptive_notification_edu_hun_text" msgid="7743367744129536610">"El volumen y las alertas se reducen por hasta 2 minutos si recibes muchas notificaciones a la vez."</string> <string name="go_to_adaptive_notification_settings" msgid="2423690125178298479">"Desactivar"</string> <string name="unlock_to_see_notif_text" msgid="7439033907167561227">"Desbloquea para ver notificaciones anteriores"</string> <string name="quick_settings_disclosure_parental_controls" msgid="2114102871438223600">"Tu padre o madre administra este dispositivo"</string> @@ -1226,7 +1232,6 @@ <string name="accessibility_fingerprint_bouncer" msgid="7189102492498735519">"Se requiere de una autenticación. Toca el sensor de huellas dactilares para autenticarte."</string> <string name="ongoing_phone_call_content_description" msgid="5332334388483099947">"Llamada en curso"</string> <string name="mobile_data_settings_title" msgid="3955246641380064901">"Datos móviles"</string> - <string name="preference_summary_default_combination" msgid="8453246369903749670">"<xliff:g id="STATE">%1$s</xliff:g>/<xliff:g id="NETWORKMODE">%2$s</xliff:g>"</string> <string name="mobile_data_connection_active" msgid="944490013299018227">"Conexión establecida"</string> <string name="mobile_data_temp_connection_active" msgid="4590222725908806824">"Conectado temporalmente"</string> <string name="mobile_data_poor_connection" msgid="819617772268371434">"Conexión deficiente"</string> @@ -1380,7 +1385,10 @@ <string name="touchpad_tutorial_done_button" msgid="176168488821755503">"Listo"</string> <string name="touchpad_tutorial_gesture_done" msgid="4784438360736821255">"¡Bien hecho!"</string> <string name="touchpad_back_gesture_action_title" msgid="7199067250654332735">"Atrás"</string> - <string name="touchpad_back_gesture_guidance" msgid="4222430588599527272">"Para volver, desliza tres dedos hacia la derecha o izquierda en cualquier lugar del panel táctil."</string> + <!-- no translation found for touchpad_back_gesture_guidance (6263750214998421587) --> + <skip /> + <!-- no translation found for touchpad_back_gesture_finished (5353616006999726249) --> + <skip /> <string name="touchpad_back_gesture_animation_content_description" msgid="2646107450922379918">"Panel táctil en el que aparecen tres dedos que se mueven hacia la derecha y la izquierda"</string> <string name="touchpad_back_gesture_screen_animation_content_description" msgid="4036267494237748710">"Pantalla de un dispositivo en la que aparece una animación del gesto atrás"</string> <string name="keyboard_backlight_dialog_title" msgid="8273102932345564724">"Retroiluminación del teclado"</string> @@ -1388,28 +1396,16 @@ <string name="home_controls_dream_label" msgid="6567105701292324257">"Controles de la casa"</string> <string name="home_controls_dream_description" msgid="4644150952104035789">"Usa rápidamente los controles de la casa como protector de pantalla"</string> <string name="volume_undo_action" msgid="5815519725211877114">"Deshacer"</string> - <!-- no translation found for back_edu_toast_content (4530314597378982956) --> - <skip /> - <!-- no translation found for home_edu_toast_content (3381071147871955415) --> - <skip /> - <!-- no translation found for overview_edu_toast_content (5797030644017804518) --> - <skip /> - <!-- no translation found for all_apps_edu_toast_content (8807496014667211562) --> - <skip /> - <!-- no translation found for back_edu_notification_title (5624780717751357278) --> - <skip /> - <!-- no translation found for back_edu_notification_content (2497557451540954068) --> - <skip /> - <!-- no translation found for home_edu_notification_title (6097902076909654045) --> - <skip /> - <!-- no translation found for home_edu_notification_content (6631697734535766588) --> - <skip /> - <!-- no translation found for overview_edu_notification_title (1265824157319562406) --> - <skip /> - <!-- no translation found for overview_edu_notification_content (3578204677648432500) --> - <skip /> - <!-- no translation found for all_apps_edu_notification_title (372262997265569063) --> - <skip /> - <!-- no translation found for all_apps_edu_notification_content (3255070575694025585) --> - <skip /> + <string name="back_edu_toast_content" msgid="4530314597378982956">"Para ir hacia atrás, desliza hacia la izquierda o la derecha con tres dedos en el panel táctil"</string> + <string name="home_edu_toast_content" msgid="3381071147871955415">"Para ir a la pantalla principal, desliza hacia arriba con tres dedos en el panel táctil"</string> + <string name="overview_edu_toast_content" msgid="5797030644017804518">"Para ver las apps recientes, desliza hacia arriba con tres dedos y mantén presionado el panel táctil"</string> + <string name="all_apps_edu_toast_content" msgid="8807496014667211562">"Para ver todas las apps, presiona la tecla de acción en el teclado"</string> + <string name="back_edu_notification_title" msgid="5624780717751357278">"Usa el panel táctil para ir hacia atrás"</string> + <string name="back_edu_notification_content" msgid="2497557451540954068">"Desliza hacia la izquierda o la derecha con tres dedos. Presiona para aprender más gestos."</string> + <string name="home_edu_notification_title" msgid="6097902076909654045">"Usa el panel táctil para ir a la pantalla principal"</string> + <string name="home_edu_notification_content" msgid="6631697734535766588">"Desliza hacia arriba con tres dedos. Presiona para aprender más gestos."</string> + <string name="overview_edu_notification_title" msgid="1265824157319562406">"Usa el panel táctil para ver las apps recientes"</string> + <string name="overview_edu_notification_content" msgid="3578204677648432500">"Desliza hacia arriba con tres dedos y mantenlos presionados. Presiona para aprender más gestos."</string> + <string name="all_apps_edu_notification_title" msgid="372262997265569063">"Usa el teclado para ver todas las apps"</string> + <string name="all_apps_edu_notification_content" msgid="3255070575694025585">"Presiona la tecla de acción en cualquier momento. Presiona para aprender más gestos."</string> </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 5c1341af8185..869efff07bdf 100644 --- a/packages/SystemUI/res/values-es-rUS/tiles_states_strings.xml +++ b/packages/SystemUI/res/values-es-rUS/tiles_states_strings.xml @@ -56,11 +56,6 @@ <item msgid="5376619709702103243">"Desactivado"</item> <item msgid="4875147066469902392">"Activado"</item> </string-array> - <string-array name="tile_states_modes"> - <item msgid="7764936419245199023">"No disponible"</item> - <item msgid="2004750556637773692">"No"</item> - <item msgid="8968530753931637871">"Sí"</item> - </string-array> <string-array name="tile_states_flashlight"> <item msgid="3465257127433353857">"No disponible"</item> <item msgid="5044688398303285224">"Desactivada"</item> diff --git a/packages/SystemUI/res/values-es/strings.xml b/packages/SystemUI/res/values-es/strings.xml index 544939d5f093..3aff0fa85b7c 100644 --- a/packages/SystemUI/res/values-es/strings.xml +++ b/packages/SystemUI/res/values-es/strings.xml @@ -388,6 +388,9 @@ <string name="performance" msgid="6552785217174378320">"Rendimiento"</string> <string name="user_interface" msgid="3712869377953950887">"Interfaz de usuario"</string> <string name="thermal" msgid="6758074791325414831">"Temperatura"</string> + <string name="custom" msgid="3337456985275158299">"Personalizado"</string> + <string name="custom_trace_settings_dialog_title" msgid="2608570500144830554">"Ajustes de rastreo personalizados"</string> + <string name="restore_default" msgid="5259420807486239755">"Restaurar ajustes predeterminados"</string> <string name="quick_settings_onehanded_label" msgid="2416537930246274991">"Modo Una mano"</string> <string name="quick_settings_hearing_devices_label" msgid="7277170419679404129">"Audífonos"</string> <string name="quick_settings_hearing_devices_connected" msgid="6519069502397037781">"Activos"</string> @@ -429,9 +432,13 @@ <string name="zen_modes_dialog_title" msgid="4159138230418567383">"Modos prioritarios"</string> <string name="zen_modes_dialog_done" msgid="6654130880256438950">"Hecho"</string> <string name="zen_modes_dialog_settings" msgid="2310248023728936697">"Ajustes"</string> - <!-- no translation found for zen_mode_on (9085304934016242591) --> + <string name="zen_mode_on" msgid="9085304934016242591">"Activado"</string> + <string name="zen_mode_off" msgid="1736604456618147306">"Desactivado"</string> + <!-- no translation found for zen_mode_set_up (7457957033034460064) --> <skip /> - <!-- no translation found for zen_mode_off (1736604456618147306) --> + <!-- no translation found for zen_mode_no_manual_invocation (1769975741344633672) --> + <skip /> + <!-- no translation found for zen_mode_active_modes (1625850411578488856) --> <skip /> <string name="zen_priority_introduction" msgid="3159291973383796646">"No te molestarán los sonidos ni las vibraciones, excepto las alarmas, los recordatorios, los eventos y las llamadas que especifiques. Seguirás escuchando el contenido que quieras reproducir, como música, vídeos y juegos."</string> <string name="zen_alarms_introduction" msgid="3987266042682300470">"No te molestarán los sonidos ni las vibraciones, excepto las alarmas. Seguirás escuchando el contenido que quieras reproducir, como música, vídeos y juegos."</string> @@ -471,6 +478,8 @@ <string name="keyguard_indication_charging_time_slowly" msgid="301936949731705417">"<xliff:g id="PERCENTAGE">%2$s</xliff:g> • Carga lenta • En <xliff:g id="CHARGING_TIME_LEFT">%1$s</xliff:g> terminará de cargarse"</string> <string name="keyguard_indication_charging_time_dock" msgid="3149328898931741271">"<xliff:g id="PERCENTAGE">%2$s</xliff:g> • Cargando • Carga completa en <xliff:g id="CHARGING_TIME_LEFT">%1$s</xliff:g>"</string> <string name="accessibility_action_open_communal_hub" msgid="3081702792413787849">"Widgets en la pantalla de bloqueo"</string> + <!-- no translation found for accessibility_announcement_communal_widget_added (6911593106099328271) --> + <skip /> <string name="communal_tutorial_indicator_text" msgid="4503010353591430123">"Desliza hacia la izquierda para iniciar el tutorial de la comunidad"</string> <string name="cta_tile_button_to_open_widget_editor" msgid="3871562362382963878">"Personalizar"</string> <string name="cta_tile_button_to_dismiss" msgid="3377597875997861754">"Cerrar"</string> @@ -499,8 +508,7 @@ <string name="accessibility_action_label_place_widget" msgid="1914197458644168978">"colocar widget seleccionado"</string> <string name="communal_widget_picker_title" msgid="1953369090475731663">"Widgets para la pantalla de bloqueo"</string> <string name="communal_widget_picker_description" msgid="490515450110487871">"Cualquiera puede ver los widgets de tu pantalla de bloqueo, aunque tu tablet esté bloqueada."</string> - <!-- no translation found for accessibility_action_label_unselect_widget (1041811747619468698) --> - <skip /> + <string name="accessibility_action_label_unselect_widget" msgid="1041811747619468698">"deseleccionar widget"</string> <string name="communal_widgets_disclaimer_title" msgid="1150954395585308868">"Widgets para la pantalla de bloqueo"</string> <string name="communal_widgets_disclaimer_text" msgid="1423545475160506349">"Para abrir una aplicación usando un widget, deberás verificar que eres tú. Además, ten en cuenta que cualquier persona podrá verlos, incluso aunque tu tablet esté bloqueada. Es posible que algunos widgets no estén pensados para la pantalla de bloqueo y no sea seguro añadirlos aquí."</string> <string name="communal_widgets_disclaimer_button" msgid="4423059765740780753">"Entendido"</string> @@ -557,10 +565,8 @@ <string name="media_projection_action_text" msgid="3634906766918186440">"Empezar ahora"</string> <string name="empty_shade_text" msgid="8935967157319717412">"No hay notificaciones"</string> <string name="no_unseen_notif_text" msgid="395512586119868682">"No hay notificaciones nuevas"</string> - <!-- no translation found for adaptive_notification_edu_hun_title (7790738150177329960) --> - <skip /> - <!-- no translation found for adaptive_notification_edu_hun_text (7743367744129536610) --> - <skip /> + <string name="adaptive_notification_edu_hun_title" msgid="7790738150177329960">"Bajar el volumen de notificaciones está activado"</string> + <string name="adaptive_notification_edu_hun_text" msgid="7743367744129536610">"El volumen y las alertas de tu dispositivo se reducen durante hasta 2 minutos si recibes muchas notificaciones a la vez."</string> <string name="go_to_adaptive_notification_settings" msgid="2423690125178298479">"Desactivar"</string> <string name="unlock_to_see_notif_text" msgid="7439033907167561227">"Desbloquea para ver notificaciones anteriores"</string> <string name="quick_settings_disclosure_parental_controls" msgid="2114102871438223600">"Este dispositivo lo gestionan tu padre o tu madre"</string> @@ -1226,7 +1232,6 @@ <string name="accessibility_fingerprint_bouncer" msgid="7189102492498735519">"Autenticación obligatoria. Toca el sensor de huellas digitales para autenticarte."</string> <string name="ongoing_phone_call_content_description" msgid="5332334388483099947">"Llamada en curso"</string> <string name="mobile_data_settings_title" msgid="3955246641380064901">"Datos móviles"</string> - <string name="preference_summary_default_combination" msgid="8453246369903749670">"<xliff:g id="STATE">%1$s</xliff:g> / <xliff:g id="NETWORKMODE">%2$s</xliff:g>"</string> <string name="mobile_data_connection_active" msgid="944490013299018227">"Conectado"</string> <string name="mobile_data_temp_connection_active" msgid="4590222725908806824">"Conectada temporalmente"</string> <string name="mobile_data_poor_connection" msgid="819617772268371434">"Conexión inestable"</string> @@ -1380,7 +1385,10 @@ <string name="touchpad_tutorial_done_button" msgid="176168488821755503">"Hecho"</string> <string name="touchpad_tutorial_gesture_done" msgid="4784438360736821255">"¡Bien hecho!"</string> <string name="touchpad_back_gesture_action_title" msgid="7199067250654332735">"Atrás"</string> - <string name="touchpad_back_gesture_guidance" msgid="4222430588599527272">"Para volver, desliza tres dedos hacia la izquierda o la derecha en cualquier punto del panel táctil."</string> + <!-- no translation found for touchpad_back_gesture_guidance (6263750214998421587) --> + <skip /> + <!-- no translation found for touchpad_back_gesture_finished (5353616006999726249) --> + <skip /> <string name="touchpad_back_gesture_animation_content_description" msgid="2646107450922379918">"Panel táctil con tres dedos moviéndose hacia la derecha y la izquierda"</string> <string name="touchpad_back_gesture_screen_animation_content_description" msgid="4036267494237748710">"Pantalla del dispositivo que muestra una animación del gesto para volver atrás"</string> <string name="keyboard_backlight_dialog_title" msgid="8273102932345564724">"Retroiluminación del teclado"</string> @@ -1388,28 +1396,16 @@ <string name="home_controls_dream_label" msgid="6567105701292324257">"Controles de la casa"</string> <string name="home_controls_dream_description" msgid="4644150952104035789">"Usa los controles de tu casa como salvapantallas"</string> <string name="volume_undo_action" msgid="5815519725211877114">"Deshacer"</string> - <!-- no translation found for back_edu_toast_content (4530314597378982956) --> - <skip /> - <!-- no translation found for home_edu_toast_content (3381071147871955415) --> - <skip /> - <!-- no translation found for overview_edu_toast_content (5797030644017804518) --> - <skip /> - <!-- no translation found for all_apps_edu_toast_content (8807496014667211562) --> - <skip /> - <!-- no translation found for back_edu_notification_title (5624780717751357278) --> - <skip /> - <!-- no translation found for back_edu_notification_content (2497557451540954068) --> - <skip /> - <!-- no translation found for home_edu_notification_title (6097902076909654045) --> - <skip /> - <!-- no translation found for home_edu_notification_content (6631697734535766588) --> - <skip /> - <!-- no translation found for overview_edu_notification_title (1265824157319562406) --> - <skip /> - <!-- no translation found for overview_edu_notification_content (3578204677648432500) --> - <skip /> - <!-- no translation found for all_apps_edu_notification_title (372262997265569063) --> - <skip /> - <!-- no translation found for all_apps_edu_notification_content (3255070575694025585) --> - <skip /> + <string name="back_edu_toast_content" msgid="4530314597378982956">"Para volver atrás, desliza hacia la izquierda o la derecha con tres dedos en el panel táctil"</string> + <string name="home_edu_toast_content" msgid="3381071147871955415">"Para ir a la pantalla de inicio, desliza hacia arriba con tres dedos en el panel táctil"</string> + <string name="overview_edu_toast_content" msgid="5797030644017804518">"Para ver las aplicaciones recientes, desliza hacia arriba y mantén pulsado el panel táctil con tres dedos"</string> + <string name="all_apps_edu_toast_content" msgid="8807496014667211562">"Para ver todas tus aplicaciones, pulsa la tecla de acción de tu teclado"</string> + <string name="back_edu_notification_title" msgid="5624780717751357278">"Usa el panel táctil para volver atrás"</string> + <string name="back_edu_notification_content" msgid="2497557451540954068">"Desliza hacia la izquierda o hacia la derecha con tres dedos. Toca para aprender a usar más gestos."</string> + <string name="home_edu_notification_title" msgid="6097902076909654045">"Usa el panel táctil para ir a la pantalla de inicio"</string> + <string name="home_edu_notification_content" msgid="6631697734535766588">"Desliza hacia arriba con tres dedos. Toca para aprender a usar más gestos."</string> + <string name="overview_edu_notification_title" msgid="1265824157319562406">"Usa el panel táctil para ver las aplicaciones recientes"</string> + <string name="overview_edu_notification_content" msgid="3578204677648432500">"Desliza hacia arriba y mantén pulsado con tres dedos. Toca para aprender a usar más gestos."</string> + <string name="all_apps_edu_notification_title" msgid="372262997265569063">"Usa el teclado para ver todas las aplicaciones"</string> + <string name="all_apps_edu_notification_content" msgid="3255070575694025585">"Pulsa la tecla de acción en cualquier momento. Toca para aprender a usar más gestos."</string> </resources> diff --git a/packages/SystemUI/res/values-es/tiles_states_strings.xml b/packages/SystemUI/res/values-es/tiles_states_strings.xml index fa0b40e77b88..08644e1cbe40 100644 --- a/packages/SystemUI/res/values-es/tiles_states_strings.xml +++ b/packages/SystemUI/res/values-es/tiles_states_strings.xml @@ -56,11 +56,6 @@ <item msgid="5376619709702103243">"Desactivado"</item> <item msgid="4875147066469902392">"Activado"</item> </string-array> - <string-array name="tile_states_modes"> - <item msgid="7764936419245199023">"No disponible"</item> - <item msgid="2004750556637773692">"Desactivado"</item> - <item msgid="8968530753931637871">"Activado"</item> - </string-array> <string-array name="tile_states_flashlight"> <item msgid="3465257127433353857">"No disponible"</item> <item msgid="5044688398303285224">"Desactivado"</item> diff --git a/packages/SystemUI/res/values-et/strings.xml b/packages/SystemUI/res/values-et/strings.xml index fa981faad87b..5b38ff61e5d4 100644 --- a/packages/SystemUI/res/values-et/strings.xml +++ b/packages/SystemUI/res/values-et/strings.xml @@ -388,6 +388,9 @@ <string name="performance" msgid="6552785217174378320">"Jõudlus"</string> <string name="user_interface" msgid="3712869377953950887">"Kasutajaliides"</string> <string name="thermal" msgid="6758074791325414831">"Soojus"</string> + <string name="custom" msgid="3337456985275158299">"Kohandatud"</string> + <string name="custom_trace_settings_dialog_title" msgid="2608570500144830554">"Kohandatud jälgimise seaded"</string> + <string name="restore_default" msgid="5259420807486239755">"Vaikeseadete taastamine"</string> <string name="quick_settings_onehanded_label" msgid="2416537930246274991">"Ühekäerežiim"</string> <string name="quick_settings_hearing_devices_label" msgid="7277170419679404129">"Kuuldeseadmed"</string> <string name="quick_settings_hearing_devices_connected" msgid="6519069502397037781">"Ühendatud"</string> @@ -429,9 +432,13 @@ <string name="zen_modes_dialog_title" msgid="4159138230418567383">"Prioriteetsed režiimid"</string> <string name="zen_modes_dialog_done" msgid="6654130880256438950">"Valmis"</string> <string name="zen_modes_dialog_settings" msgid="2310248023728936697">"Seaded"</string> - <!-- no translation found for zen_mode_on (9085304934016242591) --> + <string name="zen_mode_on" msgid="9085304934016242591">"Sees"</string> + <string name="zen_mode_off" msgid="1736604456618147306">"Väljas"</string> + <!-- no translation found for zen_mode_set_up (7457957033034460064) --> <skip /> - <!-- no translation found for zen_mode_off (1736604456618147306) --> + <!-- no translation found for zen_mode_no_manual_invocation (1769975741344633672) --> + <skip /> + <!-- no translation found for zen_mode_active_modes (1625850411578488856) --> <skip /> <string name="zen_priority_introduction" msgid="3159291973383796646">"Helid ja värinad ei sega teid. Kuulete siiski enda määratud äratusi, meeldetuletusi, sündmusi ja helistajaid. Samuti kuulete kõike, mille esitamise ise valite, sh muusika, videod ja mängud."</string> <string name="zen_alarms_introduction" msgid="3987266042682300470">"Helid ja värinad ei sega teid. Kuulete siiski äratusi. Samuti kuulete kõike, mille esitamise ise valite, sh muusika, videod ja mängud."</string> @@ -471,6 +478,8 @@ <string name="keyguard_indication_charging_time_slowly" msgid="301936949731705417">"<xliff:g id="PERCENTAGE">%2$s</xliff:g> • Aeglane laadimine • Täis <xliff:g id="CHARGING_TIME_LEFT">%1$s</xliff:g> pärast"</string> <string name="keyguard_indication_charging_time_dock" msgid="3149328898931741271">"<xliff:g id="PERCENTAGE">%2$s</xliff:g> • Laadimine • Täis <xliff:g id="CHARGING_TIME_LEFT">%1$s</xliff:g> pärast"</string> <string name="accessibility_action_open_communal_hub" msgid="3081702792413787849">"Lukustuskuva vidinad"</string> + <!-- no translation found for accessibility_announcement_communal_widget_added (6911593106099328271) --> + <skip /> <string name="communal_tutorial_indicator_text" msgid="4503010353591430123">"Ühise õpetuse käivitamiseks pühkige vasakule"</string> <string name="cta_tile_button_to_open_widget_editor" msgid="3871562362382963878">"Kohandage"</string> <string name="cta_tile_button_to_dismiss" msgid="3377597875997861754">"Loobuge"</string> @@ -499,8 +508,7 @@ <string name="accessibility_action_label_place_widget" msgid="1914197458644168978">"asetage valitud vidin"</string> <string name="communal_widget_picker_title" msgid="1953369090475731663">"Lukustuskuva vidinad"</string> <string name="communal_widget_picker_description" msgid="490515450110487871">"Igaüks saab vaadata luk.kuval olevaid vidinaid, isegi kui tahvelarvuti on lukus."</string> - <!-- no translation found for accessibility_action_label_unselect_widget (1041811747619468698) --> - <skip /> + <string name="accessibility_action_label_unselect_widget" msgid="1041811747619468698">"tühistage vidina valimine"</string> <string name="communal_widgets_disclaimer_title" msgid="1150954395585308868">"Lukustuskuva vidinad"</string> <string name="communal_widgets_disclaimer_text" msgid="1423545475160506349">"Rakenduse avamiseks vidina abil peate kinnitama, et see olete teie. Samuti pidage meeles, et kõik saavad vidinaid vaadata, isegi kui teie tahvelarvuti on lukus. Mõni vidin ei pruugi olla ette nähtud teie lukustuskuva jaoks ja seda pole turvaline siia lisada."</string> <string name="communal_widgets_disclaimer_button" msgid="4423059765740780753">"Selge"</string> @@ -557,10 +565,8 @@ <string name="media_projection_action_text" msgid="3634906766918186440">"Alusta kohe"</string> <string name="empty_shade_text" msgid="8935967157319717412">"Märguandeid pole"</string> <string name="no_unseen_notif_text" msgid="395512586119868682">"Uusi märguandeid ei ole"</string> - <!-- no translation found for adaptive_notification_edu_hun_title (7790738150177329960) --> - <skip /> - <!-- no translation found for adaptive_notification_edu_hun_text (7743367744129536610) --> - <skip /> + <string name="adaptive_notification_edu_hun_title" msgid="7790738150177329960">"Märguannete summutamine on sees"</string> + <string name="adaptive_notification_edu_hun_text" msgid="7743367744129536610">"Kui saate korraga liiga palju märguandeid, vähendab seade automaatselt helitugevust ja minimeerib märguanded kuni kaheks minutiks."</string> <string name="go_to_adaptive_notification_settings" msgid="2423690125178298479">"Lülita välja"</string> <string name="unlock_to_see_notif_text" msgid="7439033907167561227">"Vanemate märguannete nägemiseks avage"</string> <string name="quick_settings_disclosure_parental_controls" msgid="2114102871438223600">"Seda seadet haldab sinu vanem"</string> @@ -1226,7 +1232,6 @@ <string name="accessibility_fingerprint_bouncer" msgid="7189102492498735519">"Vajalik on autentimine. Puudutage autentimiseks sõrmejäljeandurit."</string> <string name="ongoing_phone_call_content_description" msgid="5332334388483099947">"Käimasolev telefonikõne"</string> <string name="mobile_data_settings_title" msgid="3955246641380064901">"Mobiilne andmeside"</string> - <string name="preference_summary_default_combination" msgid="8453246369903749670">"<xliff:g id="STATE">%1$s</xliff:g> / <xliff:g id="NETWORKMODE">%2$s</xliff:g>"</string> <string name="mobile_data_connection_active" msgid="944490013299018227">"Ühendatud"</string> <string name="mobile_data_temp_connection_active" msgid="4590222725908806824">"Ajutiselt ühendatud"</string> <string name="mobile_data_poor_connection" msgid="819617772268371434">"Kehv ühendus"</string> @@ -1380,7 +1385,10 @@ <string name="touchpad_tutorial_done_button" msgid="176168488821755503">"Valmis"</string> <string name="touchpad_tutorial_gesture_done" msgid="4784438360736821255">"Väga hea!"</string> <string name="touchpad_back_gesture_action_title" msgid="7199067250654332735">"Tagasi"</string> - <string name="touchpad_back_gesture_guidance" msgid="4222430588599527272">"Tagasiliikumiseks pühkige puuteplaadil kolme sõrmega vasakule või paremale."</string> + <!-- no translation found for touchpad_back_gesture_guidance (6263750214998421587) --> + <skip /> + <!-- no translation found for touchpad_back_gesture_finished (5353616006999726249) --> + <skip /> <string name="touchpad_back_gesture_animation_content_description" msgid="2646107450922379918">"Puuteplaat kolme paremale ja vasakule liikuva sõrmega"</string> <string name="touchpad_back_gesture_screen_animation_content_description" msgid="4036267494237748710">"Seadme ekraanil näidatakse tagasiliigutuse animatsiooni"</string> <string name="keyboard_backlight_dialog_title" msgid="8273102932345564724">"Klaviatuuri taustavalgustus"</string> @@ -1388,28 +1396,16 @@ <string name="home_controls_dream_label" msgid="6567105701292324257">"Kodu juhtelemendid"</string> <string name="home_controls_dream_description" msgid="4644150952104035789">"Juurdepääs kodu juhtelementidele ekraanisäästjalt"</string> <string name="volume_undo_action" msgid="5815519725211877114">"Võta tagasi"</string> - <!-- no translation found for back_edu_toast_content (4530314597378982956) --> - <skip /> - <!-- no translation found for home_edu_toast_content (3381071147871955415) --> - <skip /> - <!-- no translation found for overview_edu_toast_content (5797030644017804518) --> - <skip /> - <!-- no translation found for all_apps_edu_toast_content (8807496014667211562) --> - <skip /> - <!-- no translation found for back_edu_notification_title (5624780717751357278) --> - <skip /> - <!-- no translation found for back_edu_notification_content (2497557451540954068) --> - <skip /> - <!-- no translation found for home_edu_notification_title (6097902076909654045) --> - <skip /> - <!-- no translation found for home_edu_notification_content (6631697734535766588) --> - <skip /> - <!-- no translation found for overview_edu_notification_title (1265824157319562406) --> - <skip /> - <!-- no translation found for overview_edu_notification_content (3578204677648432500) --> - <skip /> - <!-- no translation found for all_apps_edu_notification_title (372262997265569063) --> - <skip /> - <!-- no translation found for all_apps_edu_notification_content (3255070575694025585) --> - <skip /> + <string name="back_edu_toast_content" msgid="4530314597378982956">"Tagasiliikumiseks pühkige puuteplaadil kolme sõrmega vasakule või paremale"</string> + <string name="home_edu_toast_content" msgid="3381071147871955415">"Avakuvale liikumiseks pühkige puuteplaadil kolme sõrmega üles"</string> + <string name="overview_edu_toast_content" msgid="5797030644017804518">"Hiljutiste rakenduste kuvamiseks pühkige puuteplaadil kolme sõrmega üles ja hoidke sõrmi puuteplaadil"</string> + <string name="all_apps_edu_toast_content" msgid="8807496014667211562">"Kõigi oma rakenduste kuvamiseks vajutage klaviatuuril toiminguklahvi"</string> + <string name="back_edu_notification_title" msgid="5624780717751357278">"Puuteplaadi kasutamine tagasiliikumiseks"</string> + <string name="back_edu_notification_content" msgid="2497557451540954068">"Pühkige kolme sõrmega vasakule või paremale. Puudutage žestide kohta lisateabe saamiseks."</string> + <string name="home_edu_notification_title" msgid="6097902076909654045">"Puuteplaadi kasutamine avakuvale liikumiseks"</string> + <string name="home_edu_notification_content" msgid="6631697734535766588">"Pühkige kolme sõrmega üles. Puudutage žestide kohta lisateabe saamiseks."</string> + <string name="overview_edu_notification_title" msgid="1265824157319562406">"Puuteplaadi kasutamine hiljutiste rakenduste kuvamiseks"</string> + <string name="overview_edu_notification_content" msgid="3578204677648432500">"Pühkige kolme sõrmega üles ja hoidke sõrmi plaadil. Puudutage žestide kohta lisateabe saamiseks."</string> + <string name="all_apps_edu_notification_title" msgid="372262997265569063">"Klaviatuuri kasutamine kõigi rakenduste kuvamiseks"</string> + <string name="all_apps_edu_notification_content" msgid="3255070575694025585">"Vajutage soovitud ajal toiminguklahvi. Puudutage žestide kohta lisateabe saamiseks."</string> </resources> diff --git a/packages/SystemUI/res/values-et/tiles_states_strings.xml b/packages/SystemUI/res/values-et/tiles_states_strings.xml index 65bf1a9d1c19..704649e77b86 100644 --- a/packages/SystemUI/res/values-et/tiles_states_strings.xml +++ b/packages/SystemUI/res/values-et/tiles_states_strings.xml @@ -56,11 +56,6 @@ <item msgid="5376619709702103243">"Väljas"</item> <item msgid="4875147066469902392">"Sees"</item> </string-array> - <string-array name="tile_states_modes"> - <item msgid="7764936419245199023">"Pole saadaval"</item> - <item msgid="2004750556637773692">"Väljas"</item> - <item msgid="8968530753931637871">"Sees"</item> - </string-array> <string-array name="tile_states_flashlight"> <item msgid="3465257127433353857">"Pole saadaval"</item> <item msgid="5044688398303285224">"Väljas"</item> diff --git a/packages/SystemUI/res/values-eu/strings.xml b/packages/SystemUI/res/values-eu/strings.xml index 70949691bfaa..6471c3bc131d 100644 --- a/packages/SystemUI/res/values-eu/strings.xml +++ b/packages/SystemUI/res/values-eu/strings.xml @@ -388,6 +388,9 @@ <string name="performance" msgid="6552785217174378320">"Errendimendua"</string> <string name="user_interface" msgid="3712869377953950887">"Erabiltzaile-interfazea"</string> <string name="thermal" msgid="6758074791325414831">"Termikoa"</string> + <string name="custom" msgid="3337456985275158299">"Pertsonalizatua"</string> + <string name="custom_trace_settings_dialog_title" msgid="2608570500144830554">"Arrasto pertsonalizatuen ezarpenak"</string> + <string name="restore_default" msgid="5259420807486239755">"Leheneratu balio lehenetsia"</string> <string name="quick_settings_onehanded_label" msgid="2416537930246274991">"Esku bakarreko modua"</string> <string name="quick_settings_hearing_devices_label" msgid="7277170419679404129">"Entzumen-gailuak"</string> <string name="quick_settings_hearing_devices_connected" msgid="6519069502397037781">"Aktibo"</string> @@ -429,9 +432,13 @@ <string name="zen_modes_dialog_title" msgid="4159138230418567383">"Lehentasunezko moduak"</string> <string name="zen_modes_dialog_done" msgid="6654130880256438950">"Eginda"</string> <string name="zen_modes_dialog_settings" msgid="2310248023728936697">"Ezarpenak"</string> - <!-- no translation found for zen_mode_on (9085304934016242591) --> + <string name="zen_mode_on" msgid="9085304934016242591">"Aktibatuta"</string> + <string name="zen_mode_off" msgid="1736604456618147306">"Desaktibatuta"</string> + <!-- no translation found for zen_mode_set_up (7457957033034460064) --> <skip /> - <!-- no translation found for zen_mode_off (1736604456618147306) --> + <!-- no translation found for zen_mode_no_manual_invocation (1769975741344633672) --> + <skip /> + <!-- no translation found for zen_mode_active_modes (1625850411578488856) --> <skip /> <string name="zen_priority_introduction" msgid="3159291973383796646">"Gailuak ez du egingo ez soinurik ez dardararik, baina alarmak, gertaera eta abisuen tonuak, eta aukeratzen dituzun deitzaileen dei-tonuak joko ditu. Bestalde, zuk erreproduzitutako guztia entzungo duzu, besteak beste, musika, bideoak eta jokoak."</string> <string name="zen_alarms_introduction" msgid="3987266042682300470">"Gailuak ez du egingo ez soinurik ez dardararik, baina alarmak joko ditu. Hala ere, zuk erreproduzitutako guztia entzun ahal izango duzu, besteak beste, musika, bideoak eta jokoak."</string> @@ -471,6 +478,8 @@ <string name="keyguard_indication_charging_time_slowly" msgid="301936949731705417">"<xliff:g id="PERCENTAGE">%2$s</xliff:g> • Mantso kargatzen • <xliff:g id="CHARGING_TIME_LEFT">%1$s</xliff:g> guztiz kargatu arte"</string> <string name="keyguard_indication_charging_time_dock" msgid="3149328898931741271">"<xliff:g id="PERCENTAGE">%2$s</xliff:g> • Kargatzen • <xliff:g id="CHARGING_TIME_LEFT">%1$s</xliff:g> guztiz kargatu arte"</string> <string name="accessibility_action_open_communal_hub" msgid="3081702792413787849">"Pantaila blokeatuko widgetak"</string> + <!-- no translation found for accessibility_announcement_communal_widget_added (6911593106099328271) --> + <skip /> <string name="communal_tutorial_indicator_text" msgid="4503010353591430123">"Tutorial komuna hasteko, pasatu hatza ezkerrera"</string> <string name="cta_tile_button_to_open_widget_editor" msgid="3871562362382963878">"Pertsonalizatu"</string> <string name="cta_tile_button_to_dismiss" msgid="3377597875997861754">"Baztertu"</string> @@ -499,8 +508,7 @@ <string name="accessibility_action_label_place_widget" msgid="1914197458644168978">"kokatu hautatutako widgeta"</string> <string name="communal_widget_picker_title" msgid="1953369090475731663">"Pantaila blokeatuko widgetak"</string> <string name="communal_widget_picker_description" msgid="490515450110487871">"Edonork ikus ditzake pantaila blokeatuko widgetak, tableta blokeatuta badago ere."</string> - <!-- no translation found for accessibility_action_label_unselect_widget (1041811747619468698) --> - <skip /> + <string name="accessibility_action_label_unselect_widget" msgid="1041811747619468698">"desautatu widgeta"</string> <string name="communal_widgets_disclaimer_title" msgid="1150954395585308868">"Pantaila blokeatuko widgetak"</string> <string name="communal_widgets_disclaimer_text" msgid="1423545475160506349">"Aplikazio bat widget baten bidez irekitzeko, zeu zarela egiaztatu beharko duzu. Gainera, kontuan izan edonork ikusi ahalko dituela halako widgetak, tableta blokeatuta badago ere. Baliteke widget batzuk pantaila blokeaturako egokiak ez izatea, eta agian ez da segurua haiek bertan gehitzea."</string> <string name="communal_widgets_disclaimer_button" msgid="4423059765740780753">"Ados"</string> @@ -557,10 +565,8 @@ <string name="media_projection_action_text" msgid="3634906766918186440">"Hasi"</string> <string name="empty_shade_text" msgid="8935967157319717412">"Ez dago jakinarazpenik"</string> <string name="no_unseen_notif_text" msgid="395512586119868682">"Ez dago jakinarazpen berririk"</string> - <!-- no translation found for adaptive_notification_edu_hun_title (7790738150177329960) --> - <skip /> - <!-- no translation found for adaptive_notification_edu_hun_text (7743367744129536610) --> - <skip /> + <string name="adaptive_notification_edu_hun_title" msgid="7790738150177329960">"Jakinarazpenak arintzeko ezarpena aktibatuta dago"</string> + <string name="adaptive_notification_edu_hun_text" msgid="7743367744129536610">"Aldi berean jakinarazpen gehiegi jasotzen badituzu, gailuaren bolumena eta alertak automatikoki murriztuko dira 2 minutuz (gehienez)."</string> <string name="go_to_adaptive_notification_settings" msgid="2423690125178298479">"Desaktibatu"</string> <string name="unlock_to_see_notif_text" msgid="7439033907167561227">"Jakinarazpen zaharragoak ikusteko, desblokeatu"</string> <string name="quick_settings_disclosure_parental_controls" msgid="2114102871438223600">"Zure gurasoak kudeatzen du gailua"</string> @@ -1226,7 +1232,6 @@ <string name="accessibility_fingerprint_bouncer" msgid="7189102492498735519">"Autentifikazioa behar da. Autentifikatzeko, ukitu hatz-marken sentsorea."</string> <string name="ongoing_phone_call_content_description" msgid="5332334388483099947">"Telefono-dei bat abian da"</string> <string name="mobile_data_settings_title" msgid="3955246641380064901">"Datu-konexioa"</string> - <string name="preference_summary_default_combination" msgid="8453246369903749670">"<xliff:g id="STATE">%1$s</xliff:g> (<xliff:g id="NETWORKMODE">%2$s</xliff:g>)"</string> <string name="mobile_data_connection_active" msgid="944490013299018227">"Konektatuta"</string> <string name="mobile_data_temp_connection_active" msgid="4590222725908806824">"Aldi baterako konektatuta"</string> <string name="mobile_data_poor_connection" msgid="819617772268371434">"Konexio ahula"</string> @@ -1380,7 +1385,10 @@ <string name="touchpad_tutorial_done_button" msgid="176168488821755503">"Eginda"</string> <string name="touchpad_tutorial_gesture_done" msgid="4784438360736821255">"Bikain!"</string> <string name="touchpad_back_gesture_action_title" msgid="7199067250654332735">"Egin atzera"</string> - <string name="touchpad_back_gesture_guidance" msgid="4222430588599527272">"Atzera egiteko, pasatu 3 hatz ezkerrera edo eskuinera ukipen-panelean."</string> + <!-- no translation found for touchpad_back_gesture_guidance (6263750214998421587) --> + <skip /> + <!-- no translation found for touchpad_back_gesture_finished (5353616006999726249) --> + <skip /> <string name="touchpad_back_gesture_animation_content_description" msgid="2646107450922379918">"3 hatz ukipen-panel baten gainean eskuinera eta ezkerrera mugitzen erakusten duen irudia"</string> <string name="touchpad_back_gesture_screen_animation_content_description" msgid="4036267494237748710">"Gailuaren pantailan atzera egiteko keinuaren animazioa erakusten duen irudia"</string> <string name="keyboard_backlight_dialog_title" msgid="8273102932345564724">"Teklatuaren hondoko argia"</string> @@ -1388,28 +1396,16 @@ <string name="home_controls_dream_label" msgid="6567105701292324257">"Etxeko gailuen kontrola"</string> <string name="home_controls_dream_description" msgid="4644150952104035789">"Kontrolatu etxeko gailuak pantaila-babesletik"</string> <string name="volume_undo_action" msgid="5815519725211877114">"Desegin"</string> - <!-- no translation found for back_edu_toast_content (4530314597378982956) --> - <skip /> - <!-- no translation found for home_edu_toast_content (3381071147871955415) --> - <skip /> - <!-- no translation found for overview_edu_toast_content (5797030644017804518) --> - <skip /> - <!-- no translation found for all_apps_edu_toast_content (8807496014667211562) --> - <skip /> - <!-- no translation found for back_edu_notification_title (5624780717751357278) --> - <skip /> - <!-- no translation found for back_edu_notification_content (2497557451540954068) --> - <skip /> - <!-- no translation found for home_edu_notification_title (6097902076909654045) --> - <skip /> - <!-- no translation found for home_edu_notification_content (6631697734535766588) --> - <skip /> - <!-- no translation found for overview_edu_notification_title (1265824157319562406) --> - <skip /> - <!-- no translation found for overview_edu_notification_content (3578204677648432500) --> - <skip /> - <!-- no translation found for all_apps_edu_notification_title (372262997265569063) --> - <skip /> - <!-- no translation found for all_apps_edu_notification_content (3255070575694025585) --> - <skip /> + <string name="back_edu_toast_content" msgid="4530314597378982956">"Atzera egiteko, pasatu 3 hatz ukipen-panelean ezkerrera edo eskuinera"</string> + <string name="home_edu_toast_content" msgid="3381071147871955415">"Hasierako pantailara joateko, pasatu 3 hatz ukipen-pantailan"</string> + <string name="overview_edu_toast_content" msgid="5797030644017804518">"Azkenaldiko aplikazioak ikusteko, pasatu 3 hatz ukipen-panelean gora eta eduki sakatuta"</string> + <string name="all_apps_edu_toast_content" msgid="8807496014667211562">"Aplikazio guztiak ikusteko, sakatu teklatuko ekintza-tekla"</string> + <string name="back_edu_notification_title" msgid="5624780717751357278">"Erabili ukipen-panela atzera egiteko"</string> + <string name="back_edu_notification_content" msgid="2497557451540954068">"Pasatu 3 hatz ezkerrera edo eskuinera. Sakatu keinu gehiago ikasteko."</string> + <string name="home_edu_notification_title" msgid="6097902076909654045">"Erabili ukipen-panela hasierako pantailara joateko"</string> + <string name="home_edu_notification_content" msgid="6631697734535766588">"Pasatu 3 hatz. Sakatu keinu gehiago ikasteko."</string> + <string name="overview_edu_notification_title" msgid="1265824157319562406">"Erabili ukipen-panela azkenaldiko aplikazioak ikusteko"</string> + <string name="overview_edu_notification_content" msgid="3578204677648432500">"Pasatu 3 hatz gora eta eduki sakatuta. Sakatu keinu gehiago ikasteko."</string> + <string name="all_apps_edu_notification_title" msgid="372262997265569063">"Erabili teklatua aplikazio guztiak ikusteko"</string> + <string name="all_apps_edu_notification_content" msgid="3255070575694025585">"Sakatu ekintza-tekla edonoiz. Sakatu keinu gehiago ikasteko."</string> </resources> diff --git a/packages/SystemUI/res/values-eu/tiles_states_strings.xml b/packages/SystemUI/res/values-eu/tiles_states_strings.xml index 75162bcc6257..13e14e0502c4 100644 --- a/packages/SystemUI/res/values-eu/tiles_states_strings.xml +++ b/packages/SystemUI/res/values-eu/tiles_states_strings.xml @@ -56,11 +56,6 @@ <item msgid="5376619709702103243">"Desaktibatuta"</item> <item msgid="4875147066469902392">"Aktibatuta"</item> </string-array> - <string-array name="tile_states_modes"> - <item msgid="7764936419245199023">"Ez dago erabilgarri"</item> - <item msgid="2004750556637773692">"Desaktibatuta"</item> - <item msgid="8968530753931637871">"Aktibatuta"</item> - </string-array> <string-array name="tile_states_flashlight"> <item msgid="3465257127433353857">"Ez dago erabilgarri"</item> <item msgid="5044688398303285224">"Desaktibatuta"</item> diff --git a/packages/SystemUI/res/values-fa/strings.xml b/packages/SystemUI/res/values-fa/strings.xml index 0c09567a087c..f4b9d9ea000c 100644 --- a/packages/SystemUI/res/values-fa/strings.xml +++ b/packages/SystemUI/res/values-fa/strings.xml @@ -388,6 +388,9 @@ <string name="performance" msgid="6552785217174378320">"عملکرد"</string> <string name="user_interface" msgid="3712869377953950887">"میانای کاربر"</string> <string name="thermal" msgid="6758074791325414831">"حرارتی"</string> + <string name="custom" msgid="3337456985275158299">"سفارشی"</string> + <string name="custom_trace_settings_dialog_title" msgid="2608570500144830554">"تنظیمات ردیابی سفارشی"</string> + <string name="restore_default" msgid="5259420807486239755">"بازیابی پیشفرض"</string> <string name="quick_settings_onehanded_label" msgid="2416537930246274991">"حالت یکدستی"</string> <string name="quick_settings_hearing_devices_label" msgid="7277170419679404129">"سمعک"</string> <string name="quick_settings_hearing_devices_connected" msgid="6519069502397037781">"فعال"</string> @@ -429,9 +432,13 @@ <string name="zen_modes_dialog_title" msgid="4159138230418567383">"حالتهای اولویتدار"</string> <string name="zen_modes_dialog_done" msgid="6654130880256438950">"تمام"</string> <string name="zen_modes_dialog_settings" msgid="2310248023728936697">"تنظیمات"</string> - <!-- no translation found for zen_mode_on (9085304934016242591) --> + <string name="zen_mode_on" msgid="9085304934016242591">"روشن"</string> + <string name="zen_mode_off" msgid="1736604456618147306">"خاموش"</string> + <!-- no translation found for zen_mode_set_up (7457957033034460064) --> <skip /> - <!-- no translation found for zen_mode_off (1736604456618147306) --> + <!-- no translation found for zen_mode_no_manual_invocation (1769975741344633672) --> + <skip /> + <!-- no translation found for zen_mode_active_modes (1625850411578488856) --> <skip /> <string name="zen_priority_introduction" msgid="3159291973383796646">"بهجز هشدارها، یادآوریها، رویدادها و تماسگیرندگانی که خودتان مشخص میکنید، هیچ صدا و لرزشی نخواهید داشت. همچنان صدای مواردی را که پخش میکنید میشنوید (ازجمله صدای موسیقی، ویدیو و بازی)."</string> <string name="zen_alarms_introduction" msgid="3987266042682300470">"بهجز هشدارها، هیچ صدا و لرزشی نخواهید داشت. همچنان صدای مواردی را که پخش میکنید میشنوید (ازجمله صدای موسیقی، ویدیو و بازی)."</string> @@ -471,6 +478,8 @@ <string name="keyguard_indication_charging_time_slowly" msgid="301936949731705417">"<xliff:g id="PERCENTAGE">%2$s</xliff:g> • درحال شارژ کردن آهسته • <xliff:g id="CHARGING_TIME_LEFT">%1$s</xliff:g> تا شارژ کامل"</string> <string name="keyguard_indication_charging_time_dock" msgid="3149328898931741271">"<xliff:g id="PERCENTAGE">%2$s</xliff:g> • درحال شارژ شدن • <xliff:g id="CHARGING_TIME_LEFT">%1$s</xliff:g> تا شارژ کامل"</string> <string name="accessibility_action_open_communal_hub" msgid="3081702792413787849">"ابزارکها در صفحه قفل"</string> + <!-- no translation found for accessibility_announcement_communal_widget_added (6911593106099328271) --> + <skip /> <string name="communal_tutorial_indicator_text" msgid="4503010353591430123">"برای شروع آموزش گامبهگام عمومی، تند بهچپ بکشید"</string> <string name="cta_tile_button_to_open_widget_editor" msgid="3871562362382963878">"سفارشیسازی"</string> <string name="cta_tile_button_to_dismiss" msgid="3377597875997861754">"بستن"</string> @@ -499,8 +508,7 @@ <string name="accessibility_action_label_place_widget" msgid="1914197458644168978">"جایگذاری ابزارک انتخابشده"</string> <string name="communal_widget_picker_title" msgid="1953369090475731663">"ابزارههای صفحه قفل"</string> <string name="communal_widget_picker_description" msgid="490515450110487871">"همه میتوانند ابزارهها را در صفحه قفل شما ببینند، حتی اگر رایانه لوحی قفل باشد."</string> - <!-- no translation found for accessibility_action_label_unselect_widget (1041811747619468698) --> - <skip /> + <string name="accessibility_action_label_unselect_widget" msgid="1041811747619468698">"لغو انتخاب ابزاره"</string> <string name="communal_widgets_disclaimer_title" msgid="1150954395585308868">"ابزارکهای صفحه قفل"</string> <string name="communal_widgets_disclaimer_text" msgid="1423545475160506349">"برای باز کردن برنامه بااستفاده از ابزارک، باید هویت خودتان را بهتأیید برسانید. همچنین، بهخاطر داشته باشید که همه میتوانند آنها را مشاهده کنند، حتی وقتی رایانه لوحیتان قفل است. برخیاز ابزارکها ممکن است برای صفحه قفل درنظر گرفته نشده باشند و ممکن است اضافه کردن آنها در اینجا ناامن باشد."</string> <string name="communal_widgets_disclaimer_button" msgid="4423059765740780753">"متوجهام"</string> @@ -557,10 +565,8 @@ <string name="media_projection_action_text" msgid="3634906766918186440">"اکنون شروع کنید"</string> <string name="empty_shade_text" msgid="8935967157319717412">"اعلانی موجود نیست"</string> <string name="no_unseen_notif_text" msgid="395512586119868682">"اعلان جدیدی وجود ندارد"</string> - <!-- no translation found for adaptive_notification_edu_hun_title (7790738150177329960) --> - <skip /> - <!-- no translation found for adaptive_notification_edu_hun_text (7743367744129536610) --> - <skip /> + <string name="adaptive_notification_edu_hun_title" msgid="7790738150177329960">"«استراحت اعلانها» روشن است"</string> + <string name="adaptive_notification_edu_hun_text" msgid="7743367744129536610">"وقتی بهطور همزمان تعداد بسیار زیادی اعلان دریافت کنید، میزان صدای دستگاه و هشدارها بهطور خودکار تا ۲ دقیقه کاهش مییابد."</string> <string name="go_to_adaptive_notification_settings" msgid="2423690125178298479">"خاموش کردن"</string> <string name="unlock_to_see_notif_text" msgid="7439033907167561227">"برای دیدن اعلانهای قبلی قفل را باز کنید"</string> <string name="quick_settings_disclosure_parental_controls" msgid="2114102871438223600">"این دستگاه را ولیتان مدیریت میکند"</string> @@ -1226,7 +1232,6 @@ <string name="accessibility_fingerprint_bouncer" msgid="7189102492498735519">"اصالتسنجی لازم است. برای اصالتسنجی، حسگر اثر انگشت را لمس کنید."</string> <string name="ongoing_phone_call_content_description" msgid="5332334388483099947">"تماس تلفنی درحال انجام"</string> <string name="mobile_data_settings_title" msgid="3955246641380064901">"داده تلفن همراه"</string> - <string name="preference_summary_default_combination" msgid="8453246369903749670">"<xliff:g id="STATE">%1$s</xliff:g> / <xliff:g id="NETWORKMODE">%2$s</xliff:g>"</string> <string name="mobile_data_connection_active" msgid="944490013299018227">"متصل است"</string> <string name="mobile_data_temp_connection_active" msgid="4590222725908806824">"موقتاً متصل است"</string> <string name="mobile_data_poor_connection" msgid="819617772268371434">"اتصال ضعیف"</string> @@ -1380,7 +1385,10 @@ <string name="touchpad_tutorial_done_button" msgid="176168488821755503">"تمام"</string> <string name="touchpad_tutorial_gesture_done" msgid="4784438360736821255">"عالی است!"</string> <string name="touchpad_back_gesture_action_title" msgid="7199067250654332735">"برگشتن"</string> - <string name="touchpad_back_gesture_guidance" msgid="4222430588599527272">"برای برگشتن، در هر جایی از صفحه لمسی، با سه انگشت تند بهچپ یا راست بکشید."</string> + <!-- no translation found for touchpad_back_gesture_guidance (6263750214998421587) --> + <skip /> + <!-- no translation found for touchpad_back_gesture_finished (5353616006999726249) --> + <skip /> <string name="touchpad_back_gesture_animation_content_description" msgid="2646107450922379918">"صفحه لمسی که سه انگشت را درحال حرکت بهسمت راست و چپ نشان میدهد"</string> <string name="touchpad_back_gesture_screen_animation_content_description" msgid="4036267494237748710">"صفحهنمایش دستگاه درحال نمایش پویانمایی مربوط به اشاره برگشتن"</string> <string name="keyboard_backlight_dialog_title" msgid="8273102932345564724">"نور پسزمینه صفحهکلید"</string> @@ -1388,28 +1396,16 @@ <string name="home_controls_dream_label" msgid="6567105701292324257">"کنترل خانه هوشمند"</string> <string name="home_controls_dream_description" msgid="4644150952104035789">"به کنترل خانه هوشمند بهعنوان محافظ صفحهنمایش دسترسی سریع دارید"</string> <string name="volume_undo_action" msgid="5815519725211877114">"واگرداندن"</string> - <!-- no translation found for back_edu_toast_content (4530314597378982956) --> - <skip /> - <!-- no translation found for home_edu_toast_content (3381071147871955415) --> - <skip /> - <!-- no translation found for overview_edu_toast_content (5797030644017804518) --> - <skip /> - <!-- no translation found for all_apps_edu_toast_content (8807496014667211562) --> - <skip /> - <!-- no translation found for back_edu_notification_title (5624780717751357278) --> - <skip /> - <!-- no translation found for back_edu_notification_content (2497557451540954068) --> - <skip /> - <!-- no translation found for home_edu_notification_title (6097902076909654045) --> - <skip /> - <!-- no translation found for home_edu_notification_content (6631697734535766588) --> - <skip /> - <!-- no translation found for overview_edu_notification_title (1265824157319562406) --> - <skip /> - <!-- no translation found for overview_edu_notification_content (3578204677648432500) --> - <skip /> - <!-- no translation found for all_apps_edu_notification_title (372262997265569063) --> - <skip /> - <!-- no translation found for all_apps_edu_notification_content (3255070575694025585) --> - <skip /> + <string name="back_edu_toast_content" msgid="4530314597378982956">"برای برگشتن، در صفحه لمسی با سه انگشت تند بهچپ یا راست بکشید"</string> + <string name="home_edu_toast_content" msgid="3381071147871955415">"برای رفتن به صفحه اصلی، در صفحه لمسی با سه انگشت تند بهبالا بکشید"</string> + <string name="overview_edu_toast_content" msgid="5797030644017804518">"برای مشاهده برنامههای اخیر، در صفحه لمسی با سه انگشت تند بهبالا بکشید و نگه دارید"</string> + <string name="all_apps_edu_toast_content" msgid="8807496014667211562">"برای مشاهده همه برنامهها، دکمه کنش در صفحهکلید را فشار دهید"</string> + <string name="back_edu_notification_title" msgid="5624780717751357278">"برای برگشتن از صفحه لمسی استفاده کنید"</string> + <string name="back_edu_notification_content" msgid="2497557451540954068">"با سه انگشت تند بهچپ یا راست بکشید. برای آشنایی با اشارههای بیشتر، تکضرب بزنید."</string> + <string name="home_edu_notification_title" msgid="6097902076909654045">"برای رفتن به صفحه اصلی از صفحه لمسی استفاده کنید"</string> + <string name="home_edu_notification_content" msgid="6631697734535766588">"با سه انگشت تند بهبالا بکشید. برای آشنایی با اشارههای بیشتر، تکضرب بزنید."</string> + <string name="overview_edu_notification_title" msgid="1265824157319562406">"برای مشاهده برنامههای اخیر از صفحه لمسی استفاده کنید"</string> + <string name="overview_edu_notification_content" msgid="3578204677648432500">"با سه انگشت تند بهبالا بکشید و نگه دارید. برای آشنایی با اشارههای بیشتر، تکضرب بزنید."</string> + <string name="all_apps_edu_notification_title" msgid="372262997265569063">"برای مشاهده همه برنامهها، از صفحهکلید استفاده کنید"</string> + <string name="all_apps_edu_notification_content" msgid="3255070575694025585">"در هرزمانی دکمه کنش را فشار دهید. برای آشنایی با اشارههای بیشتر، تکضرب بزنید."</string> </resources> diff --git a/packages/SystemUI/res/values-fa/tiles_states_strings.xml b/packages/SystemUI/res/values-fa/tiles_states_strings.xml index b2444e8cd8ab..756b442f5fc4 100644 --- a/packages/SystemUI/res/values-fa/tiles_states_strings.xml +++ b/packages/SystemUI/res/values-fa/tiles_states_strings.xml @@ -56,11 +56,6 @@ <item msgid="5376619709702103243">"خاموش"</item> <item msgid="4875147066469902392">"روشن"</item> </string-array> - <string-array name="tile_states_modes"> - <item msgid="7764936419245199023">"دردسترس نیست"</item> - <item msgid="2004750556637773692">"خاموش"</item> - <item msgid="8968530753931637871">"روشن"</item> - </string-array> <string-array name="tile_states_flashlight"> <item msgid="3465257127433353857">"دردسترس نیست"</item> <item msgid="5044688398303285224">"خاموش"</item> diff --git a/packages/SystemUI/res/values-fi/strings.xml b/packages/SystemUI/res/values-fi/strings.xml index 10a2dffdc4dd..79962f01846f 100644 --- a/packages/SystemUI/res/values-fi/strings.xml +++ b/packages/SystemUI/res/values-fi/strings.xml @@ -388,6 +388,9 @@ <string name="performance" msgid="6552785217174378320">"Suorituskyky"</string> <string name="user_interface" msgid="3712869377953950887">"Käyttöliittymä"</string> <string name="thermal" msgid="6758074791325414831">"Lämpökamera"</string> + <string name="custom" msgid="3337456985275158299">"Yksilöity"</string> + <string name="custom_trace_settings_dialog_title" msgid="2608570500144830554">"Yksilöidyt jäljittämisasetukset"</string> + <string name="restore_default" msgid="5259420807486239755">"Palauta oletus"</string> <string name="quick_settings_onehanded_label" msgid="2416537930246274991">"Yhden käden moodi"</string> <string name="quick_settings_hearing_devices_label" msgid="7277170419679404129">"Kuulolaitteet"</string> <string name="quick_settings_hearing_devices_connected" msgid="6519069502397037781">"Aktiivinen"</string> @@ -429,9 +432,13 @@ <string name="zen_modes_dialog_title" msgid="4159138230418567383">"Prioriteettitilat"</string> <string name="zen_modes_dialog_done" msgid="6654130880256438950">"Valmis"</string> <string name="zen_modes_dialog_settings" msgid="2310248023728936697">"Asetukset"</string> - <!-- no translation found for zen_mode_on (9085304934016242591) --> + <string name="zen_mode_on" msgid="9085304934016242591">"Päällä"</string> + <string name="zen_mode_off" msgid="1736604456618147306">"Pois päältä"</string> + <!-- no translation found for zen_mode_set_up (7457957033034460064) --> <skip /> - <!-- no translation found for zen_mode_off (1736604456618147306) --> + <!-- no translation found for zen_mode_no_manual_invocation (1769975741344633672) --> + <skip /> + <!-- no translation found for zen_mode_active_modes (1625850411578488856) --> <skip /> <string name="zen_priority_introduction" msgid="3159291973383796646">"Äänet ja värinät eivät häiritse sinua, paitsi jos ne ovat hälytyksiä, muistutuksia, tapahtumia tai määrittämiäsi soittajia. Kuulet edelleen kaiken valitsemasi sisällön, kuten musiikin, videot ja pelit."</string> <string name="zen_alarms_introduction" msgid="3987266042682300470">"Äänet ja värinät eivät häiritse sinua, paitsi jos ne ovat hälytyksiä. Kuulet edelleen kaiken valitsemasi sisällön, kuten musiikin, videot ja pelit."</string> @@ -471,6 +478,8 @@ <string name="keyguard_indication_charging_time_slowly" msgid="301936949731705417">"<xliff:g id="PERCENTAGE">%2$s</xliff:g> • Latautuu hitaasti • Täynnä <xliff:g id="CHARGING_TIME_LEFT">%1$s</xliff:g> päästä"</string> <string name="keyguard_indication_charging_time_dock" msgid="3149328898931741271">"<xliff:g id="PERCENTAGE">%2$s</xliff:g> • Latautuu • Täynnä <xliff:g id="CHARGING_TIME_LEFT">%1$s</xliff:g> päästä"</string> <string name="accessibility_action_open_communal_hub" msgid="3081702792413787849">"Widgetit lukitusnäytöllä"</string> + <!-- no translation found for accessibility_announcement_communal_widget_added (6911593106099328271) --> + <skip /> <string name="communal_tutorial_indicator_text" msgid="4503010353591430123">"Aloita yhteisöesittely pyyhkäisemällä vasemmalle"</string> <string name="cta_tile_button_to_open_widget_editor" msgid="3871562362382963878">"Muokkaa"</string> <string name="cta_tile_button_to_dismiss" msgid="3377597875997861754">"Hylkää"</string> @@ -499,8 +508,7 @@ <string name="accessibility_action_label_place_widget" msgid="1914197458644168978">"aseta valittu widget"</string> <string name="communal_widget_picker_title" msgid="1953369090475731663">"Lukitusnäytön widgetit"</string> <string name="communal_widget_picker_description" msgid="490515450110487871">"Kaikki voivat nähdä widgetit lukitusnäytöllä, vaikka tabletti olisi lukittuna."</string> - <!-- no translation found for accessibility_action_label_unselect_widget (1041811747619468698) --> - <skip /> + <string name="accessibility_action_label_unselect_widget" msgid="1041811747619468698">"poista widgetin valinta"</string> <string name="communal_widgets_disclaimer_title" msgid="1150954395585308868">"Lukitusnäytön widgetit"</string> <string name="communal_widgets_disclaimer_text" msgid="1423545475160506349">"Jos haluat avata sovelluksen käyttämällä widgetiä, sinun täytyy vahvistaa henkilöllisyytesi. Muista myös, että widgetit näkyvät kaikille, vaikka tabletti olisi lukittuna. Jotkin widgetit on ehkä tarkoitettu lukitusnäytölle, ja niiden lisääminen tänne ei välttämättä ole turvallista."</string> <string name="communal_widgets_disclaimer_button" msgid="4423059765740780753">"Selvä"</string> @@ -557,10 +565,8 @@ <string name="media_projection_action_text" msgid="3634906766918186440">"Aloita nyt"</string> <string name="empty_shade_text" msgid="8935967157319717412">"Ei ilmoituksia"</string> <string name="no_unseen_notif_text" msgid="395512586119868682">"Ei uusia ilmoituksia"</string> - <!-- no translation found for adaptive_notification_edu_hun_title (7790738150177329960) --> - <skip /> - <!-- no translation found for adaptive_notification_edu_hun_text (7743367744129536610) --> - <skip /> + <string name="adaptive_notification_edu_hun_title" msgid="7790738150177329960">"Ilmoitusten vaimennus on päällä"</string> + <string name="adaptive_notification_edu_hun_text" msgid="7743367744129536610">"Äänenvoimakkuus ja ilmoitukset vaimennetaan enintään 2 minuutiksi, kun saat paljon ilmoituksia."</string> <string name="go_to_adaptive_notification_settings" msgid="2423690125178298479">"Laita pois päältä"</string> <string name="unlock_to_see_notif_text" msgid="7439033907167561227">"Avaa lukitus niin näet ilmoituksia"</string> <string name="quick_settings_disclosure_parental_controls" msgid="2114102871438223600">"Vanhempasi ylläpitää tätä laitetta"</string> @@ -1226,7 +1232,6 @@ <string name="accessibility_fingerprint_bouncer" msgid="7189102492498735519">"Todennus vaaditaan. Todenna koskettamalla sormenjälkitunnistinta."</string> <string name="ongoing_phone_call_content_description" msgid="5332334388483099947">"Puhelu käynnissä"</string> <string name="mobile_data_settings_title" msgid="3955246641380064901">"Mobiilidata"</string> - <string name="preference_summary_default_combination" msgid="8453246369903749670">"<xliff:g id="STATE">%1$s</xliff:g>/<xliff:g id="NETWORKMODE">%2$s</xliff:g>"</string> <string name="mobile_data_connection_active" msgid="944490013299018227">"Yhdistetty"</string> <string name="mobile_data_temp_connection_active" msgid="4590222725908806824">"Väliaikaisesti yhdistetty"</string> <string name="mobile_data_poor_connection" msgid="819617772268371434">"Heikko yhteys"</string> @@ -1380,7 +1385,10 @@ <string name="touchpad_tutorial_done_button" msgid="176168488821755503">"Valmis"</string> <string name="touchpad_tutorial_gesture_done" msgid="4784438360736821255">"Hienoa!"</string> <string name="touchpad_back_gesture_action_title" msgid="7199067250654332735">"Takaisin"</string> - <string name="touchpad_back_gesture_guidance" msgid="4222430588599527272">"Jos haluat siirtyä takaisin, pyyhkäise kosketuslevyllä vasemmalle tai oikealle kolmella sormella."</string> + <!-- no translation found for touchpad_back_gesture_guidance (6263750214998421587) --> + <skip /> + <!-- no translation found for touchpad_back_gesture_finished (5353616006999726249) --> + <skip /> <string name="touchpad_back_gesture_animation_content_description" msgid="2646107450922379918">"Kosketuslevy, jolla kolme sormea liikkuu oikealle ja vasemmalle"</string> <string name="touchpad_back_gesture_screen_animation_content_description" msgid="4036267494237748710">"Laitteen näyttö, jolla näkyy animaatio takaisin-eleestä"</string> <string name="keyboard_backlight_dialog_title" msgid="8273102932345564724">"Näppämistön taustavalo"</string> @@ -1388,28 +1396,16 @@ <string name="home_controls_dream_label" msgid="6567105701292324257">"Kodin ohjaus"</string> <string name="home_controls_dream_description" msgid="4644150952104035789">"Avaa kodin ohjaus nopeasti näytönsäästäjän kautta"</string> <string name="volume_undo_action" msgid="5815519725211877114">"Kumoa"</string> - <!-- no translation found for back_edu_toast_content (4530314597378982956) --> - <skip /> - <!-- no translation found for home_edu_toast_content (3381071147871955415) --> - <skip /> - <!-- no translation found for overview_edu_toast_content (5797030644017804518) --> - <skip /> - <!-- no translation found for all_apps_edu_toast_content (8807496014667211562) --> - <skip /> - <!-- no translation found for back_edu_notification_title (5624780717751357278) --> - <skip /> - <!-- no translation found for back_edu_notification_content (2497557451540954068) --> - <skip /> - <!-- no translation found for home_edu_notification_title (6097902076909654045) --> - <skip /> - <!-- no translation found for home_edu_notification_content (6631697734535766588) --> - <skip /> - <!-- no translation found for overview_edu_notification_title (1265824157319562406) --> - <skip /> - <!-- no translation found for overview_edu_notification_content (3578204677648432500) --> - <skip /> - <!-- no translation found for all_apps_edu_notification_title (372262997265569063) --> - <skip /> - <!-- no translation found for all_apps_edu_notification_content (3255070575694025585) --> - <skip /> + <string name="back_edu_toast_content" msgid="4530314597378982956">"Jos haluat siirtyä takaisin, pyyhkäise kosketuslevyllä vasemmalle tai oikealle kolmella sormella."</string> + <string name="home_edu_toast_content" msgid="3381071147871955415">"Jos haluat siirtyä aloitussivulle, pyyhkäise kosketuslevyllä ylös kolmella sormella"</string> + <string name="overview_edu_toast_content" msgid="5797030644017804518">"Näet äskeiset sovellukset, kun pyyhkäiset ylös ja pidät kosketuslevyä painettuna kolmella sormella."</string> + <string name="all_apps_edu_toast_content" msgid="8807496014667211562">"Jos haluat nähdä kaikki sovellukset, paina näppäimistön toimintonäppäintä"</string> + <string name="back_edu_notification_title" msgid="5624780717751357278">"Takaisin siirtyminen kosketuslevyn avulla"</string> + <string name="back_edu_notification_content" msgid="2497557451540954068">"Pyyhkäise vasemmalle tai oikealle kolmella sormella. Lue lisää eleistä napauttamalla."</string> + <string name="home_edu_notification_title" msgid="6097902076909654045">"Aloitusnäytölle siirtyminen kosketuslevyn avulla"</string> + <string name="home_edu_notification_content" msgid="6631697734535766588">"Pyyhkäise ylös kolmella sormella. Lue lisää eleistä napauttamalla."</string> + <string name="overview_edu_notification_title" msgid="1265824157319562406">"Äskettäin käytettyjen sovellusten näkeminen kosketuslevyn avulla"</string> + <string name="overview_edu_notification_content" msgid="3578204677648432500">"Pyyhkäise ylös ja pidä kosketuslevyä painettuna kolmella sormella. Lue lisää eleistä napauttamalla."</string> + <string name="all_apps_edu_notification_title" msgid="372262997265569063">"Kaikkien sovellusten näkeminen näppäimistön avulla"</string> + <string name="all_apps_edu_notification_content" msgid="3255070575694025585">"Voit painaa toimintonäppäintä milloin tahansa. Lue lisää eleistä napauttamalla."</string> </resources> diff --git a/packages/SystemUI/res/values-fi/tiles_states_strings.xml b/packages/SystemUI/res/values-fi/tiles_states_strings.xml index a7a6bdc109c2..5ecc95956d1c 100644 --- a/packages/SystemUI/res/values-fi/tiles_states_strings.xml +++ b/packages/SystemUI/res/values-fi/tiles_states_strings.xml @@ -56,11 +56,6 @@ <item msgid="5376619709702103243">"Poissa päältä"</item> <item msgid="4875147066469902392">"Päällä"</item> </string-array> - <string-array name="tile_states_modes"> - <item msgid="7764936419245199023">"Ei saatavilla"</item> - <item msgid="2004750556637773692">"Pois päältä"</item> - <item msgid="8968530753931637871">"Päällä"</item> - </string-array> <string-array name="tile_states_flashlight"> <item msgid="3465257127433353857">"Ei saatavilla"</item> <item msgid="5044688398303285224">"Poissa päältä"</item> diff --git a/packages/SystemUI/res/values-fr-rCA/strings.xml b/packages/SystemUI/res/values-fr-rCA/strings.xml index b8c30eec07a0..f34ce9811a99 100644 --- a/packages/SystemUI/res/values-fr-rCA/strings.xml +++ b/packages/SystemUI/res/values-fr-rCA/strings.xml @@ -138,7 +138,7 @@ <string name="share_to_app_stop_dialog_message_single_app_generic" msgid="6681016774654578261">"Vous partagez actuellement une appli"</string> <string name="share_to_app_stop_dialog_button" msgid="6334056916284230217">"Arrêter le partage"</string> <string name="cast_screen_to_other_device_chip_accessibility_label" msgid="4687917476203009885">"Diffusion de l\'écran en cours…"</string> - <string name="cast_to_other_device_stop_dialog_title" msgid="7836517190930357326">"Arrêter de diffuser?"</string> + <string name="cast_to_other_device_stop_dialog_title" msgid="7836517190930357326">"Arrêter la diffusion?"</string> <string name="cast_to_other_device_stop_dialog_message_entire_screen_with_device" msgid="1474703115926205251">"Vous diffusez actuellement l\'intégralité de votre écran sur <xliff:g id="DEVICE_NAME">%1$s</xliff:g>"</string> <string name="cast_to_other_device_stop_dialog_message_entire_screen" msgid="8419219169553867625">"Vous diffusez actuellement l\'intégralité de votre écran sur un appareil à proximité"</string> <string name="cast_to_other_device_stop_dialog_message_specific_app_with_device" msgid="2715934698604085519">"Vous diffusez actuellement <xliff:g id="APP_BEING_SHARED_NAME">%1$s</xliff:g> sur <xliff:g id="DEVICE_NAME">%2$s</xliff:g>"</string> @@ -388,6 +388,9 @@ <string name="performance" msgid="6552785217174378320">"Performance"</string> <string name="user_interface" msgid="3712869377953950887">"Interface utilisateur"</string> <string name="thermal" msgid="6758074791325414831">"Thermique"</string> + <string name="custom" msgid="3337456985275158299">"Personnalisé"</string> + <string name="custom_trace_settings_dialog_title" msgid="2608570500144830554">"Paramètres personnalisés de la trace"</string> + <string name="restore_default" msgid="5259420807486239755">"Restaurer la valeur par défaut"</string> <string name="quick_settings_onehanded_label" msgid="2416537930246274991">"Mode Une main"</string> <string name="quick_settings_hearing_devices_label" msgid="7277170419679404129">"Appareils auditifs"</string> <string name="quick_settings_hearing_devices_connected" msgid="6519069502397037781">"Actives"</string> @@ -429,9 +432,13 @@ <string name="zen_modes_dialog_title" msgid="4159138230418567383">"Modes prioritaires"</string> <string name="zen_modes_dialog_done" msgid="6654130880256438950">"OK"</string> <string name="zen_modes_dialog_settings" msgid="2310248023728936697">"Paramètres"</string> - <!-- no translation found for zen_mode_on (9085304934016242591) --> + <string name="zen_mode_on" msgid="9085304934016242591">"Activé"</string> + <string name="zen_mode_off" msgid="1736604456618147306">"Désactivé"</string> + <!-- no translation found for zen_mode_set_up (7457957033034460064) --> <skip /> - <!-- no translation found for zen_mode_off (1736604456618147306) --> + <!-- no translation found for zen_mode_no_manual_invocation (1769975741344633672) --> + <skip /> + <!-- no translation found for zen_mode_active_modes (1625850411578488856) --> <skip /> <string name="zen_priority_introduction" msgid="3159291973383796646">"Vous ne serez pas dérangé par les sons et les vibrations, sauf pour les alarmes, les rappels, les événements et les appelants que vous sélectionnez. Vous entendrez tout ce que vous choisissez d\'écouter, y compris la musique, les vidéos et les jeux."</string> <string name="zen_alarms_introduction" msgid="3987266042682300470">"Vous ne serez pas dérangé par les sons et les vibrations, sauf pour les alarmes. Vous entendrez tout ce que vous choisissez d\'écouter, y compris la musique, les vidéos et les jeux."</string> @@ -471,6 +478,8 @@ <string name="keyguard_indication_charging_time_slowly" msgid="301936949731705417">"En recharge lente : <xliff:g id="PERCENTAGE">%2$s</xliff:g> • Terminée <xliff:g id="CHARGING_TIME_LEFT">%1$s</xliff:g>"</string> <string name="keyguard_indication_charging_time_dock" msgid="3149328898931741271">"<xliff:g id="PERCENTAGE">%2$s</xliff:g> • Recharge en cours… • Se terminera dans <xliff:g id="CHARGING_TIME_LEFT">%1$s</xliff:g>"</string> <string name="accessibility_action_open_communal_hub" msgid="3081702792413787849">"Widgets sur l\'écran de verrouillage"</string> + <!-- no translation found for accessibility_announcement_communal_widget_added (6911593106099328271) --> + <skip /> <string name="communal_tutorial_indicator_text" msgid="4503010353591430123">"Balayer l\'écran vers la gauche pour démarrer le tutoriel communautaire"</string> <string name="cta_tile_button_to_open_widget_editor" msgid="3871562362382963878">"Personnaliser"</string> <string name="cta_tile_button_to_dismiss" msgid="3377597875997861754">"Fermer"</string> @@ -499,8 +508,7 @@ <string name="accessibility_action_label_place_widget" msgid="1914197458644168978">"placer le widget sélectionné"</string> <string name="communal_widget_picker_title" msgid="1953369090475731663">"Widgets de l\'écran de verrouillage"</string> <string name="communal_widget_picker_description" msgid="490515450110487871">"N\'importe qui peut voir les widgets sur votre écran de verrouillage, même si votre tablette est verrouillée."</string> - <!-- no translation found for accessibility_action_label_unselect_widget (1041811747619468698) --> - <skip /> + <string name="accessibility_action_label_unselect_widget" msgid="1041811747619468698">"désélectionner le widget"</string> <string name="communal_widgets_disclaimer_title" msgid="1150954395585308868">"Widgets de l\'écran de verrouillage"</string> <string name="communal_widgets_disclaimer_text" msgid="1423545475160506349">"Pour ouvrir une appli à l\'aide d\'un widget, vous devrez confirmer votre identité. En outre, gardez à l\'esprit que tout le monde peut les voir, même lorsque votre tablette est verrouillée. Certains widgets n\'ont peut-être pas été conçus pour votre écran de verrouillage et il pourrait être dangereux de les ajouter ici."</string> <string name="communal_widgets_disclaimer_button" msgid="4423059765740780753">"OK"</string> @@ -557,10 +565,8 @@ <string name="media_projection_action_text" msgid="3634906766918186440">"Commencer"</string> <string name="empty_shade_text" msgid="8935967157319717412">"Aucune notification"</string> <string name="no_unseen_notif_text" msgid="395512586119868682">"Aucune nouvelle notification"</string> - <!-- no translation found for adaptive_notification_edu_hun_title (7790738150177329960) --> - <skip /> - <!-- no translation found for adaptive_notification_edu_hun_text (7743367744129536610) --> - <skip /> + <string name="adaptive_notification_edu_hun_title" msgid="7790738150177329960">"L\'atténuation des notifications est activée"</string> + <string name="adaptive_notification_edu_hun_text" msgid="7743367744129536610">"Le volume de votre appareil est réduit pendant deux minutes si vous recevez trop de notifications."</string> <string name="go_to_adaptive_notification_settings" msgid="2423690125178298479">"Désactiver"</string> <string name="unlock_to_see_notif_text" msgid="7439033907167561227">"Déverr. pour voir les anciennes notif."</string> <string name="quick_settings_disclosure_parental_controls" msgid="2114102871438223600">"Cet appareil est géré par ton parent"</string> @@ -1006,7 +1012,7 @@ <string name="privacy_type_media_projection" msgid="8136723828804251547">"enregistrement d\'écran"</string> <string name="music_controls_no_title" msgid="4166497066552290938">"Sans titre"</string> <string name="inattentive_sleep_warning_title" msgid="3891371591713990373">"Veille"</string> - <string name="font_scaling_dialog_title" msgid="6273107303850248375">"Taille de police"</string> + <string name="font_scaling_dialog_title" msgid="6273107303850248375">"Taille de la police"</string> <string name="font_scaling_smaller" msgid="1012032217622008232">"Rapetisser"</string> <string name="font_scaling_larger" msgid="5476242157436806760">"Agrandir"</string> <string name="magnification_window_title" msgid="4863914360847258333">"Fenêtre d\'agrandissement"</string> @@ -1226,7 +1232,6 @@ <string name="accessibility_fingerprint_bouncer" msgid="7189102492498735519">"Authentification requise. Touchez le capteur d\'empreintes digitales pour vous authentifier."</string> <string name="ongoing_phone_call_content_description" msgid="5332334388483099947">"Appel téléphonique en cours…"</string> <string name="mobile_data_settings_title" msgid="3955246641380064901">"Données cellulaires"</string> - <string name="preference_summary_default_combination" msgid="8453246369903749670">"<xliff:g id="STATE">%1$s</xliff:g>/<xliff:g id="NETWORKMODE">%2$s</xliff:g>"</string> <string name="mobile_data_connection_active" msgid="944490013299018227">"Connexion active"</string> <string name="mobile_data_temp_connection_active" msgid="4590222725908806824">"Connectée temporairement"</string> <string name="mobile_data_poor_connection" msgid="819617772268371434">"Connexion faible"</string> @@ -1380,7 +1385,10 @@ <string name="touchpad_tutorial_done_button" msgid="176168488821755503">"OK"</string> <string name="touchpad_tutorial_gesture_done" msgid="4784438360736821255">"Bon travail!"</string> <string name="touchpad_back_gesture_action_title" msgid="7199067250654332735">"Retour"</string> - <string name="touchpad_back_gesture_guidance" msgid="4222430588599527272">"Pour revenir en arrière, balayez vers la gauche ou la droite en utilisant trois doigts n\'importe où sur le pavé tactile."</string> + <!-- no translation found for touchpad_back_gesture_guidance (6263750214998421587) --> + <skip /> + <!-- no translation found for touchpad_back_gesture_finished (5353616006999726249) --> + <skip /> <string name="touchpad_back_gesture_animation_content_description" msgid="2646107450922379918">"Pavé tactile montrant trois doigts se déplaçant à droite et à gauche"</string> <string name="touchpad_back_gesture_screen_animation_content_description" msgid="4036267494237748710">"Écran de l\'appareil montrant l\'animation pour le geste de retour"</string> <string name="keyboard_backlight_dialog_title" msgid="8273102932345564724">"Rétroéclairage du clavier"</string> @@ -1388,28 +1396,16 @@ <string name="home_controls_dream_label" msgid="6567105701292324257">"Domotique"</string> <string name="home_controls_dream_description" msgid="4644150952104035789">"Accès rapide : domotique sous forme d\'Écran de veille"</string> <string name="volume_undo_action" msgid="5815519725211877114">"Annuler"</string> - <!-- no translation found for back_edu_toast_content (4530314597378982956) --> - <skip /> - <!-- no translation found for home_edu_toast_content (3381071147871955415) --> - <skip /> - <!-- no translation found for overview_edu_toast_content (5797030644017804518) --> - <skip /> - <!-- no translation found for all_apps_edu_toast_content (8807496014667211562) --> - <skip /> - <!-- no translation found for back_edu_notification_title (5624780717751357278) --> - <skip /> - <!-- no translation found for back_edu_notification_content (2497557451540954068) --> - <skip /> - <!-- no translation found for home_edu_notification_title (6097902076909654045) --> - <skip /> - <!-- no translation found for home_edu_notification_content (6631697734535766588) --> - <skip /> - <!-- no translation found for overview_edu_notification_title (1265824157319562406) --> - <skip /> - <!-- no translation found for overview_edu_notification_content (3578204677648432500) --> - <skip /> - <!-- no translation found for all_apps_edu_notification_title (372262997265569063) --> - <skip /> - <!-- no translation found for all_apps_edu_notification_content (3255070575694025585) --> - <skip /> + <string name="back_edu_toast_content" msgid="4530314597378982956">"Pour revenir en arrière, balayez l\'écran vers la gauche ou vers la droite avec trois doigts sur le pavé tactile"</string> + <string name="home_edu_toast_content" msgid="3381071147871955415">"Pour accéder à l\'écran d\'accueil, balayez l\'écran vers le haut avec trois doigts sur le pavé tactile"</string> + <string name="overview_edu_toast_content" msgid="5797030644017804518">"Pour afficher les applis récentes, balayez l\'écran vers le haut avec trois doigts sur le pavé tactile et maintenez-les en place"</string> + <string name="all_apps_edu_toast_content" msgid="8807496014667211562">"Pour afficher toutes vos applis, appuyez sur la touche d\'action de votre clavier"</string> + <string name="back_edu_notification_title" msgid="5624780717751357278">"Utiliser votre pavé tactile pour revenir en arrière"</string> + <string name="back_edu_notification_content" msgid="2497557451540954068">"Balayez vers la gauche ou vers la droite avec trois doigts. Touchez pour apprendre d\'autres gestes."</string> + <string name="home_edu_notification_title" msgid="6097902076909654045">"Utilisez votre pavé tactile pour accéder à l\'écran d\'accueil"</string> + <string name="home_edu_notification_content" msgid="6631697734535766588">"Balayez l\'écran vers le haut avec trois doigts. Touchez pour apprendre d\'autres gestes."</string> + <string name="overview_edu_notification_title" msgid="1265824157319562406">"Utiliser le pavé tactile pour afficher les applis récentes"</string> + <string name="overview_edu_notification_content" msgid="3578204677648432500">"Balayez l\'écran vers le haut avec trois doigts et maintenez-les en place. Touchez pour apprendre d\'autres gestes."</string> + <string name="all_apps_edu_notification_title" msgid="372262997265569063">"Utiliser votre clavier pour afficher toutes les applis"</string> + <string name="all_apps_edu_notification_content" msgid="3255070575694025585">"Appuyez sur la touche d\'action à tout moment. Touchez pour apprendre d\'autres gestes."</string> </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 75be453b526f..f12634faecbb 100644 --- a/packages/SystemUI/res/values-fr-rCA/tiles_states_strings.xml +++ b/packages/SystemUI/res/values-fr-rCA/tiles_states_strings.xml @@ -56,11 +56,6 @@ <item msgid="5376619709702103243">"Désactivée"</item> <item msgid="4875147066469902392">"Activé"</item> </string-array> - <string-array name="tile_states_modes"> - <item msgid="7764936419245199023">"Non accessible"</item> - <item msgid="2004750556637773692">"Désactivé"</item> - <item msgid="8968530753931637871">"Activé"</item> - </string-array> <string-array name="tile_states_flashlight"> <item msgid="3465257127433353857">"Non disponible"</item> <item msgid="5044688398303285224">"Désactivée"</item> diff --git a/packages/SystemUI/res/values-fr/strings.xml b/packages/SystemUI/res/values-fr/strings.xml index 6fc47328d328..ad63e9e54e20 100644 --- a/packages/SystemUI/res/values-fr/strings.xml +++ b/packages/SystemUI/res/values-fr/strings.xml @@ -145,7 +145,7 @@ <string name="cast_to_other_device_stop_dialog_message_specific_app" msgid="8616103075630934513">"Vous castez actuellement <xliff:g id="APP_BEING_SHARED_NAME">%1$s</xliff:g> sur un appareil à proximité"</string> <string name="cast_to_other_device_stop_dialog_message_generic_with_device" msgid="9213582497852420203">"Vous castez actuellement du contenu sur <xliff:g id="DEVICE_NAME">%1$s</xliff:g>"</string> <string name="cast_to_other_device_stop_dialog_message_generic" msgid="4100272100480415076">"Vous castez actuellement du contenu sur un appareil à proximité"</string> - <string name="cast_to_other_device_stop_dialog_button" msgid="6420183747435521834">"Arrêter de caster du contenu"</string> + <string name="cast_to_other_device_stop_dialog_button" msgid="6420183747435521834">"Arrêter de caster"</string> <string name="close_dialog_button" msgid="4749497706540104133">"Fermer"</string> <string name="issuerecord_title" msgid="286627115110121849">"Enregistreur de problèmes"</string> <string name="issuerecord_background_processing_label" msgid="1666840264959336876">"Enregistrement du problème"</string> @@ -388,6 +388,9 @@ <string name="performance" msgid="6552785217174378320">"Performances"</string> <string name="user_interface" msgid="3712869377953950887">"Interface utilisateur"</string> <string name="thermal" msgid="6758074791325414831">"Thermique"</string> + <string name="custom" msgid="3337456985275158299">"Personnalisé"</string> + <string name="custom_trace_settings_dialog_title" msgid="2608570500144830554">"Paramètres Trace personnalisés"</string> + <string name="restore_default" msgid="5259420807486239755">"Rétablir les paramètres par défaut"</string> <string name="quick_settings_onehanded_label" msgid="2416537930246274991">"Mode une main"</string> <string name="quick_settings_hearing_devices_label" msgid="7277170419679404129">"Appareils auditifs"</string> <string name="quick_settings_hearing_devices_connected" msgid="6519069502397037781">"Actifs"</string> @@ -429,9 +432,13 @@ <string name="zen_modes_dialog_title" msgid="4159138230418567383">"Modes prioritaires"</string> <string name="zen_modes_dialog_done" msgid="6654130880256438950">"OK"</string> <string name="zen_modes_dialog_settings" msgid="2310248023728936697">"Paramètres"</string> - <!-- no translation found for zen_mode_on (9085304934016242591) --> + <string name="zen_mode_on" msgid="9085304934016242591">"Activé"</string> + <string name="zen_mode_off" msgid="1736604456618147306">"Désactivé"</string> + <!-- no translation found for zen_mode_set_up (7457957033034460064) --> <skip /> - <!-- no translation found for zen_mode_off (1736604456618147306) --> + <!-- no translation found for zen_mode_no_manual_invocation (1769975741344633672) --> + <skip /> + <!-- no translation found for zen_mode_active_modes (1625850411578488856) --> <skip /> <string name="zen_priority_introduction" msgid="3159291973383796646">"Vous ne serez pas dérangé par des sons ou des vibrations, hormis ceux des alarmes, des rappels, des événements et des appelants de votre choix. Vous entendrez encore les sons que vous choisirez de jouer, notamment la musique, les vidéos et les jeux."</string> <string name="zen_alarms_introduction" msgid="3987266042682300470">"Vous ne serez pas dérangé par des sons ou des vibrations, hormis ceux des alarmes. Vous entendrez encore les sons que vous choisirez de jouer, comme la musique, les vidéos et les jeux."</string> @@ -471,6 +478,8 @@ <string name="keyguard_indication_charging_time_slowly" msgid="301936949731705417">"<xliff:g id="PERCENTAGE">%2$s</xliff:g> • Recharge lente • Temps restant : <xliff:g id="CHARGING_TIME_LEFT">%1$s</xliff:g>"</string> <string name="keyguard_indication_charging_time_dock" msgid="3149328898931741271">"<xliff:g id="PERCENTAGE">%2$s</xliff:g> • Recharge • Temps restant : <xliff:g id="CHARGING_TIME_LEFT">%1$s</xliff:g>"</string> <string name="accessibility_action_open_communal_hub" msgid="3081702792413787849">"Widgets sur l\'écran de verrouillage"</string> + <!-- no translation found for accessibility_announcement_communal_widget_added (6911593106099328271) --> + <skip /> <string name="communal_tutorial_indicator_text" msgid="4503010353591430123">"Balayer vers la gauche pour démarrer le tutoriel collectif"</string> <string name="cta_tile_button_to_open_widget_editor" msgid="3871562362382963878">"Personnaliser"</string> <string name="cta_tile_button_to_dismiss" msgid="3377597875997861754">"Fermer"</string> @@ -499,8 +508,7 @@ <string name="accessibility_action_label_place_widget" msgid="1914197458644168978">"positionner le widget sélectionné"</string> <string name="communal_widget_picker_title" msgid="1953369090475731663">"Widgets sur l\'écran de verrouillage"</string> <string name="communal_widget_picker_description" msgid="490515450110487871">"N\'importe qui peut consulter les widgets sur votre écran de verrouillage, même si votre tablette est verrouillée."</string> - <!-- no translation found for accessibility_action_label_unselect_widget (1041811747619468698) --> - <skip /> + <string name="accessibility_action_label_unselect_widget" msgid="1041811747619468698">"désélectionner le widget"</string> <string name="communal_widgets_disclaimer_title" msgid="1150954395585308868">"Widgets pour l\'écran de verrouillage"</string> <string name="communal_widgets_disclaimer_text" msgid="1423545475160506349">"Pour ouvrir une appli à l\'aide d\'un widget, vous devez confirmer qu\'il s\'agit bien de vous. N\'oubliez pas non plus que tout le monde peut voir vos widgets, même lorsque votre tablette est verrouillée. Certains d\'entre eux n\'ont pas été conçus pour l\'écran de verrouillage et les ajouter à cet endroit peut s\'avérer dangereux."</string> <string name="communal_widgets_disclaimer_button" msgid="4423059765740780753">"OK"</string> @@ -557,10 +565,8 @@ <string name="media_projection_action_text" msgid="3634906766918186440">"Commencer"</string> <string name="empty_shade_text" msgid="8935967157319717412">"Aucune notification"</string> <string name="no_unseen_notif_text" msgid="395512586119868682">"Aucune nouvelle notification"</string> - <!-- no translation found for adaptive_notification_edu_hun_title (7790738150177329960) --> - <skip /> - <!-- no translation found for adaptive_notification_edu_hun_text (7743367744129536610) --> - <skip /> + <string name="adaptive_notification_edu_hun_title" msgid="7790738150177329960">"La limitation des notifications est activée"</string> + <string name="adaptive_notification_edu_hun_text" msgid="7743367744129536610">"Les alertes et le volume de l\'appareil sont réduits automatiquement pendant 2 minutes max. quand vous recevez trop de notifications à la fois."</string> <string name="go_to_adaptive_notification_settings" msgid="2423690125178298479">"Désactiver"</string> <string name="unlock_to_see_notif_text" msgid="7439033907167561227">"Déverrouiller pour voir anciennes notifications"</string> <string name="quick_settings_disclosure_parental_controls" msgid="2114102871438223600">"Cet appareil est géré par tes parents"</string> @@ -1226,7 +1232,6 @@ <string name="accessibility_fingerprint_bouncer" msgid="7189102492498735519">"Authentification requise. Appuyez sur le lecteur d\'empreintes digitales pour vous authentifier."</string> <string name="ongoing_phone_call_content_description" msgid="5332334388483099947">"Appel téléphonique en cours"</string> <string name="mobile_data_settings_title" msgid="3955246641380064901">"Données mobiles"</string> - <string name="preference_summary_default_combination" msgid="8453246369903749670">"<xliff:g id="STATE">%1$s</xliff:g>/<xliff:g id="NETWORKMODE">%2$s</xliff:g>"</string> <string name="mobile_data_connection_active" msgid="944490013299018227">"Connecté"</string> <string name="mobile_data_temp_connection_active" msgid="4590222725908806824">"Connexion temporaire"</string> <string name="mobile_data_poor_connection" msgid="819617772268371434">"Connexion médiocre"</string> @@ -1380,7 +1385,10 @@ <string name="touchpad_tutorial_done_button" msgid="176168488821755503">"OK"</string> <string name="touchpad_tutorial_gesture_done" msgid="4784438360736821255">"Bravo !"</string> <string name="touchpad_back_gesture_action_title" msgid="7199067250654332735">"Retour"</string> - <string name="touchpad_back_gesture_guidance" msgid="4222430588599527272">"Pour retourner en arrière, balayez vers la gauche avec trois doigts n\'importe où sur le pavé tactile."</string> + <!-- no translation found for touchpad_back_gesture_guidance (6263750214998421587) --> + <skip /> + <!-- no translation found for touchpad_back_gesture_finished (5353616006999726249) --> + <skip /> <string name="touchpad_back_gesture_animation_content_description" msgid="2646107450922379918">"Pavé tactile sur lequel trois doigts glissent vers la droite, puis vers la gauche"</string> <string name="touchpad_back_gesture_screen_animation_content_description" msgid="4036267494237748710">"Écran d\'un appareil affichant l\'animation du geste Retour"</string> <string name="keyboard_backlight_dialog_title" msgid="8273102932345564724">"Rétroéclairage du clavier"</string> @@ -1388,28 +1396,16 @@ <string name="home_controls_dream_label" msgid="6567105701292324257">"Contrôle de la maison"</string> <string name="home_controls_dream_description" msgid="4644150952104035789">"Domotique sous forme d\'économiseur d\'écran"</string> <string name="volume_undo_action" msgid="5815519725211877114">"Annuler"</string> - <!-- no translation found for back_edu_toast_content (4530314597378982956) --> - <skip /> - <!-- no translation found for home_edu_toast_content (3381071147871955415) --> - <skip /> - <!-- no translation found for overview_edu_toast_content (5797030644017804518) --> - <skip /> - <!-- no translation found for all_apps_edu_toast_content (8807496014667211562) --> - <skip /> - <!-- no translation found for back_edu_notification_title (5624780717751357278) --> - <skip /> - <!-- no translation found for back_edu_notification_content (2497557451540954068) --> - <skip /> - <!-- no translation found for home_edu_notification_title (6097902076909654045) --> - <skip /> - <!-- no translation found for home_edu_notification_content (6631697734535766588) --> - <skip /> - <!-- no translation found for overview_edu_notification_title (1265824157319562406) --> - <skip /> - <!-- no translation found for overview_edu_notification_content (3578204677648432500) --> - <skip /> - <!-- no translation found for all_apps_edu_notification_title (372262997265569063) --> - <skip /> - <!-- no translation found for all_apps_edu_notification_content (3255070575694025585) --> - <skip /> + <string name="back_edu_toast_content" msgid="4530314597378982956">"Pour retourner en arrière, glissez vers la gauche ou la droite avec trois doigts sur le pavé tactile"</string> + <string name="home_edu_toast_content" msgid="3381071147871955415">"Pour revenir à l\'accueil, balayez vers le haut avec trois doigts sur le pavé tactile"</string> + <string name="overview_edu_toast_content" msgid="5797030644017804518">"Pour afficher les applis récentes, balayez vers le haut avec trois doigts sur le pavé tactile et maintenez-les."</string> + <string name="all_apps_edu_toast_content" msgid="8807496014667211562">"Pour afficher toutes vos applis, appuyez sur la touche d\'action de votre clavier"</string> + <string name="back_edu_notification_title" msgid="5624780717751357278">"Utilisez votre pavé tactile pour revenir en arrière"</string> + <string name="back_edu_notification_content" msgid="2497557451540954068">"Balayez vers la gauche ou la droite en utilisant trois doigts. Appuyez pour apprendre d\'autres gestes."</string> + <string name="home_edu_notification_title" msgid="6097902076909654045">"Utilisez votre pavé tactile pour revenir à l\'accueil"</string> + <string name="home_edu_notification_content" msgid="6631697734535766588">"Balayez vers le haut avec trois doigts. Appuyez pour apprendre d\'autres gestes."</string> + <string name="overview_edu_notification_title" msgid="1265824157319562406">"Utilisez votre pavé tactile pour afficher les applis récentes"</string> + <string name="overview_edu_notification_content" msgid="3578204677648432500">"Balayez vers le haut en utilisant trois doigts et maintenez. Appuyez pour apprendre d\'autres gestes."</string> + <string name="all_apps_edu_notification_title" msgid="372262997265569063">"Utilisez votre clavier pour afficher toutes les applis"</string> + <string name="all_apps_edu_notification_content" msgid="3255070575694025585">"Appuyez sur la touche d\'action à tout moment. Appuyez pour apprendre d\'autres gestes."</string> </resources> diff --git a/packages/SystemUI/res/values-fr/tiles_states_strings.xml b/packages/SystemUI/res/values-fr/tiles_states_strings.xml index daa91524a148..fcdd9f0e6e3a 100644 --- a/packages/SystemUI/res/values-fr/tiles_states_strings.xml +++ b/packages/SystemUI/res/values-fr/tiles_states_strings.xml @@ -56,11 +56,6 @@ <item msgid="5376619709702103243">"Désactivé"</item> <item msgid="4875147066469902392">"Activé"</item> </string-array> - <string-array name="tile_states_modes"> - <item msgid="7764936419245199023">"Non disponible"</item> - <item msgid="2004750556637773692">"Désactivé"</item> - <item msgid="8968530753931637871">"Activé"</item> - </string-array> <string-array name="tile_states_flashlight"> <item msgid="3465257127433353857">"Indisponible"</item> <item msgid="5044688398303285224">"Désactivé"</item> diff --git a/packages/SystemUI/res/values-gl/strings.xml b/packages/SystemUI/res/values-gl/strings.xml index 7b39df7e8062..913e589c1a33 100644 --- a/packages/SystemUI/res/values-gl/strings.xml +++ b/packages/SystemUI/res/values-gl/strings.xml @@ -388,6 +388,9 @@ <string name="performance" msgid="6552785217174378320">"Rendemento"</string> <string name="user_interface" msgid="3712869377953950887">"Interface de usuario"</string> <string name="thermal" msgid="6758074791325414831">"Térmico"</string> + <string name="custom" msgid="3337456985275158299">"Personalizada"</string> + <string name="custom_trace_settings_dialog_title" msgid="2608570500144830554">"Configuración de rastrexo personalizada"</string> + <string name="restore_default" msgid="5259420807486239755">"Restaurar configuración predeterminada"</string> <string name="quick_settings_onehanded_label" msgid="2416537930246274991">"Modo dunha soa man"</string> <string name="quick_settings_hearing_devices_label" msgid="7277170419679404129">"Dispositivos auditivos"</string> <string name="quick_settings_hearing_devices_connected" msgid="6519069502397037781">"Activos"</string> @@ -431,6 +434,12 @@ <string name="zen_modes_dialog_settings" msgid="2310248023728936697">"Configuración"</string> <string name="zen_mode_on" msgid="9085304934016242591">"Activado"</string> <string name="zen_mode_off" msgid="1736604456618147306">"Desactivado"</string> + <!-- no translation found for zen_mode_set_up (7457957033034460064) --> + <skip /> + <!-- no translation found for zen_mode_no_manual_invocation (1769975741344633672) --> + <skip /> + <!-- no translation found for zen_mode_active_modes (1625850411578488856) --> + <skip /> <string name="zen_priority_introduction" msgid="3159291973383796646">"Non te molestará ningún son nin vibración, agás os procedentes de alarmas, recordatorios, eventos e os emisores de chamada especificados. Seguirás escoitando todo aquilo que decidas reproducir, mesmo a música, os vídeos e os xogos."</string> <string name="zen_alarms_introduction" msgid="3987266042682300470">"Non te molestará ningún son nin vibración, agás os procedentes de alarmas. Seguirás escoitando todo aquilo que decidas reproducir, mesmo a música, os vídeos e os xogos."</string> <string name="zen_priority_customize_button" msgid="4119213187257195047">"Personalizar"</string> @@ -469,6 +478,8 @@ <string name="keyguard_indication_charging_time_slowly" msgid="301936949731705417">"<xliff:g id="PERCENTAGE">%2$s</xliff:g> • Cargando lentamente • A carga completarase en <xliff:g id="CHARGING_TIME_LEFT">%1$s</xliff:g>"</string> <string name="keyguard_indication_charging_time_dock" msgid="3149328898931741271">"<xliff:g id="PERCENTAGE">%2$s</xliff:g> • Cargando • A carga completarase en <xliff:g id="CHARGING_TIME_LEFT">%1$s</xliff:g>"</string> <string name="accessibility_action_open_communal_hub" msgid="3081702792413787849">"Widgets na pantalla de bloqueo"</string> + <!-- no translation found for accessibility_announcement_communal_widget_added (6911593106099328271) --> + <skip /> <string name="communal_tutorial_indicator_text" msgid="4503010353591430123">"Pasa o dedo cara á esquerda para iniciar o titorial comunitario"</string> <string name="cta_tile_button_to_open_widget_editor" msgid="3871562362382963878">"Personalizar"</string> <string name="cta_tile_button_to_dismiss" msgid="3377597875997861754">"Pechar"</string> @@ -554,10 +565,8 @@ <string name="media_projection_action_text" msgid="3634906766918186440">"Iniciar agora"</string> <string name="empty_shade_text" msgid="8935967157319717412">"Non hai notificacións"</string> <string name="no_unseen_notif_text" msgid="395512586119868682">"Non hai notificacións novas"</string> - <!-- no translation found for adaptive_notification_edu_hun_title (7790738150177329960) --> - <skip /> - <!-- no translation found for adaptive_notification_edu_hun_text (7743367744129536610) --> - <skip /> + <string name="adaptive_notification_edu_hun_title" msgid="7790738150177329960">"A opción Amainar notificacións está activada"</string> + <string name="adaptive_notification_edu_hun_text" msgid="7743367744129536610">"Cando recibas moitas notificacións, o volume e as alertas reduciranse automaticamente durante ata dous minutos."</string> <string name="go_to_adaptive_notification_settings" msgid="2423690125178298479">"Desactivar"</string> <string name="unlock_to_see_notif_text" msgid="7439033907167561227">"Desbloquea para ver máis notificacións"</string> <string name="quick_settings_disclosure_parental_controls" msgid="2114102871438223600">"O teu pai ou nai xestiona este dispositivo"</string> @@ -1223,7 +1232,6 @@ <string name="accessibility_fingerprint_bouncer" msgid="7189102492498735519">"Requírese autenticación. Para autenticarte, toca o sensor de impresión dixital."</string> <string name="ongoing_phone_call_content_description" msgid="5332334388483099947">"Chamada telefónica en curso"</string> <string name="mobile_data_settings_title" msgid="3955246641380064901">"Datos móbiles"</string> - <string name="preference_summary_default_combination" msgid="8453246369903749670">"<xliff:g id="STATE">%1$s</xliff:g>/<xliff:g id="NETWORKMODE">%2$s</xliff:g>"</string> <string name="mobile_data_connection_active" msgid="944490013299018227">"Conectada"</string> <string name="mobile_data_temp_connection_active" msgid="4590222725908806824">"Conectada temporalmente"</string> <string name="mobile_data_poor_connection" msgid="819617772268371434">"Conexión deficiente"</string> @@ -1377,7 +1385,10 @@ <string name="touchpad_tutorial_done_button" msgid="176168488821755503">"Feito"</string> <string name="touchpad_tutorial_gesture_done" msgid="4784438360736821255">"Moi ben!"</string> <string name="touchpad_back_gesture_action_title" msgid="7199067250654332735">"Volver"</string> - <string name="touchpad_back_gesture_guidance" msgid="4222430588599527272">"Para volver, pasa tres dedos cara á esquerda ou cara á dereita en calquera lugar do panel táctil."</string> + <!-- no translation found for touchpad_back_gesture_guidance (6263750214998421587) --> + <skip /> + <!-- no translation found for touchpad_back_gesture_finished (5353616006999726249) --> + <skip /> <string name="touchpad_back_gesture_animation_content_description" msgid="2646107450922379918">"Panel táctil que mostra tres dedos movéndose á dereita e á esquerda"</string> <string name="touchpad_back_gesture_screen_animation_content_description" msgid="4036267494237748710">"Pantalla do dispositivo que mostra unha animación do xesto de retroceso"</string> <string name="keyboard_backlight_dialog_title" msgid="8273102932345564724">"Retroiluminación do teclado"</string> diff --git a/packages/SystemUI/res/values-gl/tiles_states_strings.xml b/packages/SystemUI/res/values-gl/tiles_states_strings.xml index 8e3fb2634039..03b934eb9cb6 100644 --- a/packages/SystemUI/res/values-gl/tiles_states_strings.xml +++ b/packages/SystemUI/res/values-gl/tiles_states_strings.xml @@ -56,11 +56,6 @@ <item msgid="5376619709702103243">"Non"</item> <item msgid="4875147066469902392">"Si"</item> </string-array> - <string-array name="tile_states_modes"> - <item msgid="7764936419245199023">"Non dispoñible"</item> - <item msgid="2004750556637773692">"Desactivado"</item> - <item msgid="8968530753931637871">"Activado"</item> - </string-array> <string-array name="tile_states_flashlight"> <item msgid="3465257127433353857">"Non dispoñible"</item> <item msgid="5044688398303285224">"Non"</item> diff --git a/packages/SystemUI/res/values-gu/strings.xml b/packages/SystemUI/res/values-gu/strings.xml index 78e86fadd500..8fd8b3e9664d 100644 --- a/packages/SystemUI/res/values-gu/strings.xml +++ b/packages/SystemUI/res/values-gu/strings.xml @@ -388,6 +388,9 @@ <string name="performance" msgid="6552785217174378320">"પર્ફોર્મન્સ"</string> <string name="user_interface" msgid="3712869377953950887">"યૂઝર ઇન્ટરફેસ"</string> <string name="thermal" msgid="6758074791325414831">"થર્મલ"</string> + <string name="custom" msgid="3337456985275158299">"કસ્ટમ"</string> + <string name="custom_trace_settings_dialog_title" msgid="2608570500144830554">"કસ્ટમ ટ્રેસ સેટિંગ"</string> + <string name="restore_default" msgid="5259420807486239755">"ડિફૉલ્ટ રિસ્ટોર કરો"</string> <string name="quick_settings_onehanded_label" msgid="2416537930246274991">"એક-હાથે વાપરો મોડ"</string> <string name="quick_settings_hearing_devices_label" msgid="7277170419679404129">"સાંભળવામાં મદદ આપતા ડિવાઇસ"</string> <string name="quick_settings_hearing_devices_connected" msgid="6519069502397037781">"સક્રિય"</string> @@ -429,9 +432,13 @@ <string name="zen_modes_dialog_title" msgid="4159138230418567383">"પ્રાધાન્યતાના મોડ"</string> <string name="zen_modes_dialog_done" msgid="6654130880256438950">"થઈ ગયું"</string> <string name="zen_modes_dialog_settings" msgid="2310248023728936697">"સેટિંગ"</string> - <!-- no translation found for zen_mode_on (9085304934016242591) --> + <string name="zen_mode_on" msgid="9085304934016242591">"ચાલુ"</string> + <string name="zen_mode_off" msgid="1736604456618147306">"બંધ"</string> + <!-- no translation found for zen_mode_set_up (7457957033034460064) --> <skip /> - <!-- no translation found for zen_mode_off (1736604456618147306) --> + <!-- no translation found for zen_mode_no_manual_invocation (1769975741344633672) --> + <skip /> + <!-- no translation found for zen_mode_active_modes (1625850411578488856) --> <skip /> <string name="zen_priority_introduction" msgid="3159291973383796646">"અલાર્મ, રિમાઇન્ડર, ઇવેન્ટ અને તમે ઉલ્લેખ કરો તે કૉલર સિવાય તમને ધ્વનિ કે વાઇબ્રેશન દ્વારા ખલેલ પહોંચાડવામાં આવશે નહીં. સંગીત, વીડિઓ અને રમતો સહિત તમે જે કંઈપણ ચલાવવાનું પસંદ કરશો તે સંભળાતું રહેશે."</string> <string name="zen_alarms_introduction" msgid="3987266042682300470">"અલાર્મ સિવાય તમને ધ્વનિ કે વાઇબ્રેશન દ્વારા ખલેલ પહોંચાડવામાં આવશે નહીં. સંગીત, વીડિઓ અને રમતો સહિત તમે જે કંઈપણ ચલાવવાનું પસંદ કરશો તે સંભળાતું રહેશે."</string> @@ -471,6 +478,8 @@ <string name="keyguard_indication_charging_time_slowly" msgid="301936949731705417">"<xliff:g id="PERCENTAGE">%2$s</xliff:g> • ધીમેથી ચાર્જ થઈ રહ્યું છે • <xliff:g id="CHARGING_TIME_LEFT">%1$s</xliff:g>માં ચાર્જ થઈ જશે"</string> <string name="keyguard_indication_charging_time_dock" msgid="3149328898931741271">"<xliff:g id="PERCENTAGE">%2$s</xliff:g> • ચાર્જ થઈ રહ્યું છે • <xliff:g id="CHARGING_TIME_LEFT">%1$s</xliff:g>માં પૂરું ચાર્જ થઈ જશે"</string> <string name="accessibility_action_open_communal_hub" msgid="3081702792413787849">"લૉક સ્ક્રીન પર વિજેટ"</string> + <!-- no translation found for accessibility_announcement_communal_widget_added (6911593106099328271) --> + <skip /> <string name="communal_tutorial_indicator_text" msgid="4503010353591430123">"કૉમ્યુનલ ટ્યૂટૉરિઅલ શરૂ કરવા માટે ડાબે સ્વાઇપ કરો"</string> <string name="cta_tile_button_to_open_widget_editor" msgid="3871562362382963878">"કસ્ટમાઇઝ કરો"</string> <string name="cta_tile_button_to_dismiss" msgid="3377597875997861754">"છોડી દો"</string> @@ -499,8 +508,7 @@ <string name="accessibility_action_label_place_widget" msgid="1914197458644168978">"પસંદ કરેલું વિજેટ મૂકો"</string> <string name="communal_widget_picker_title" msgid="1953369090475731663">"લૉક સ્ક્રીન વિજેટ"</string> <string name="communal_widget_picker_description" msgid="490515450110487871">"તમારું ટૅબ્લેટ લૉક કરેલું હોય તો પણ કોઈપણ તમારી લૉક સ્ક્રીન પર વિજેટ જોઈ શકે છે."</string> - <!-- no translation found for accessibility_action_label_unselect_widget (1041811747619468698) --> - <skip /> + <string name="accessibility_action_label_unselect_widget" msgid="1041811747619468698">"વિજેટ નાપસંદ કરો"</string> <string name="communal_widgets_disclaimer_title" msgid="1150954395585308868">"લૉક સ્ક્રીન વિજેટ"</string> <string name="communal_widgets_disclaimer_text" msgid="1423545475160506349">"વિજેટનો ઉપયોગ કરીને ઍપ ખોલવા માટે, તમારે એ ચકાસણી કરવાની જરૂર રહેશે કે આ તમે જ છો. તે ઉપરાંત, ધ્યાનમાં રાખો કે તમારું ટૅબ્લેટ લૉક કરેલું હોય તો પણ કોઈપણ વ્યક્તિ તેમને જોઈ શકે છે. અમુક વિજેટ કદાચ તમારી લૉક સ્ક્રીન માટે બનાવવામાં આવ્યા ન હોઈ શકે છે અને તેમને અહીં ઉમેરવાનું અસલામત હોઈ શકે છે."</string> <string name="communal_widgets_disclaimer_button" msgid="4423059765740780753">"સમજાઈ ગયું"</string> @@ -557,10 +565,8 @@ <string name="media_projection_action_text" msgid="3634906766918186440">"હવે શરૂ કરો"</string> <string name="empty_shade_text" msgid="8935967157319717412">"કોઈ નોટિફિકેશન નથી"</string> <string name="no_unseen_notif_text" msgid="395512586119868682">"કોઈ નવું નોટિફિકેશન નથી"</string> - <!-- no translation found for adaptive_notification_edu_hun_title (7790738150177329960) --> - <skip /> - <!-- no translation found for adaptive_notification_edu_hun_text (7743367744129536610) --> - <skip /> + <string name="adaptive_notification_edu_hun_title" msgid="7790738150177329960">"નોટિફિકેશન કૂલડાઉન ચાલુ છે"</string> + <string name="adaptive_notification_edu_hun_text" msgid="7743367744129536610">"જ્યારે તમને એકસાથે ઘણા બધા નોટિફિકેશન મળે ત્યારે તમારા ડિવાઇસનું વૉલ્યૂમ અને અલર્ટ ઑટોમૅટિક રીતે 2 મિનિટ જેટલા સમય માટે ઘટાડવામાં આવે છે."</string> <string name="go_to_adaptive_notification_settings" msgid="2423690125178298479">"બંધ કરો"</string> <string name="unlock_to_see_notif_text" msgid="7439033907167561227">"જૂના નોટિફિકેશન જોવા માટે અનલૉક કરો"</string> <string name="quick_settings_disclosure_parental_controls" msgid="2114102871438223600">"આ ડિવાઇસ તમારા માતાપિતા દ્વારા મેનેજ કરવામાં આવે છે"</string> @@ -1226,7 +1232,6 @@ <string name="accessibility_fingerprint_bouncer" msgid="7189102492498735519">"પ્રમાણીકરણ આવશ્યક છે. પ્રમાણિત કરવા માટે ફિંગરપ્રિન્ટ સેન્સરને ટચ કરો."</string> <string name="ongoing_phone_call_content_description" msgid="5332334388483099947">"ફોન કૉલ ચાલુ છે"</string> <string name="mobile_data_settings_title" msgid="3955246641380064901">"મોબાઇલ ડેટા"</string> - <string name="preference_summary_default_combination" msgid="8453246369903749670">"<xliff:g id="STATE">%1$s</xliff:g> / <xliff:g id="NETWORKMODE">%2$s</xliff:g>"</string> <string name="mobile_data_connection_active" msgid="944490013299018227">"કનેક્ટ કરેલું"</string> <string name="mobile_data_temp_connection_active" msgid="4590222725908806824">"હંગામી રીતે કનેક્ટ કર્યું"</string> <string name="mobile_data_poor_connection" msgid="819617772268371434">"નબળું કનેક્શન"</string> @@ -1380,7 +1385,10 @@ <string name="touchpad_tutorial_done_button" msgid="176168488821755503">"થઈ ગયું"</string> <string name="touchpad_tutorial_gesture_done" msgid="4784438360736821255">"ખૂબ સરસ કામ!"</string> <string name="touchpad_back_gesture_action_title" msgid="7199067250654332735">"પાછા જાઓ"</string> - <string name="touchpad_back_gesture_guidance" msgid="4222430588599527272">"પાછા જવા માટે, ત્રણ આંગળીઓનો ઉપયોગ કરીને ટચપૅડ પર કોઈપણ જગ્યાએ ડાબે કે જમણે સ્વાઇપ કરો."</string> + <!-- no translation found for touchpad_back_gesture_guidance (6263750214998421587) --> + <skip /> + <!-- no translation found for touchpad_back_gesture_finished (5353616006999726249) --> + <skip /> <string name="touchpad_back_gesture_animation_content_description" msgid="2646107450922379918">"જમણી અને ડાબી તરફ ખસી રહેલી ત્રણ આંગળીઓ બતાવતું ટચપૅડ"</string> <string name="touchpad_back_gesture_screen_animation_content_description" msgid="4036267494237748710">"પાછા જવા માટેના સંકેત માટેનું ઍનિમેશન બતાવતી ડિવાઇસ સ્ક્રીન"</string> <string name="keyboard_backlight_dialog_title" msgid="8273102932345564724">"કીબોર્ડની બૅકલાઇટ"</string> @@ -1388,28 +1396,16 @@ <string name="home_controls_dream_label" msgid="6567105701292324257">"ઘરેલું સાધનોના નિયંત્રણો"</string> <string name="home_controls_dream_description" msgid="4644150952104035789">"સ્ક્રીનસેવર તરીકે તમારા ઘરેલું સાધનોના નિયંત્રણો ઝડપથી ઍક્સેસ કરો"</string> <string name="volume_undo_action" msgid="5815519725211877114">"છેલ્લો ફેરફાર રદ કરો"</string> - <!-- no translation found for back_edu_toast_content (4530314597378982956) --> - <skip /> - <!-- no translation found for home_edu_toast_content (3381071147871955415) --> - <skip /> - <!-- no translation found for overview_edu_toast_content (5797030644017804518) --> - <skip /> - <!-- no translation found for all_apps_edu_toast_content (8807496014667211562) --> - <skip /> - <!-- no translation found for back_edu_notification_title (5624780717751357278) --> - <skip /> - <!-- no translation found for back_edu_notification_content (2497557451540954068) --> - <skip /> - <!-- no translation found for home_edu_notification_title (6097902076909654045) --> - <skip /> - <!-- no translation found for home_edu_notification_content (6631697734535766588) --> - <skip /> - <!-- no translation found for overview_edu_notification_title (1265824157319562406) --> - <skip /> - <!-- no translation found for overview_edu_notification_content (3578204677648432500) --> - <skip /> - <!-- no translation found for all_apps_edu_notification_title (372262997265569063) --> - <skip /> - <!-- no translation found for all_apps_edu_notification_content (3255070575694025585) --> - <skip /> + <string name="back_edu_toast_content" msgid="4530314597378982956">"પાછા જવા માટે, ટચપૅડ પર ત્રણ આંગળી વડે ડાબે અથવા જમણે સ્વાઇપ કરો"</string> + <string name="home_edu_toast_content" msgid="3381071147871955415">"હોમ સ્ક્રીન પર જવા માટે, ટચપૅડ પર ત્રણ આંગળીઓ વડે ઉપર સ્વાઇપ કરો"</string> + <string name="overview_edu_toast_content" msgid="5797030644017804518">"તાજેતરની ઍપ જોવા માટે, ટચપૅડ પર ત્રણ આંગળીઓ વડે ઉપર સ્વાઇપ કરો અને દબાવી રાખો"</string> + <string name="all_apps_edu_toast_content" msgid="8807496014667211562">"તમારી બધી ઍપ જોવા માટે, તમારા કીબોર્ડ પર ઍક્શન કી દબાવો"</string> + <string name="back_edu_notification_title" msgid="5624780717751357278">"પાછા જવા માટે તમારા ટચપૅડનો ઉપયોગ કરો"</string> + <string name="back_edu_notification_content" msgid="2497557451540954068">"ત્રણ આંગળીનો ઉપયોગ કરીને ડાબે અથવા જમણે સ્વાઇપ કરો. સંકેતો વિશે વધુ જાણવા માટે ટૅપ કરો."</string> + <string name="home_edu_notification_title" msgid="6097902076909654045">"હોમ સ્ક્રીન પર જવા માટે તમારા ટચપૅડનો ઉપયોગ કરો"</string> + <string name="home_edu_notification_content" msgid="6631697734535766588">"ત્રણ આંગળીનો ઉપયોગ કરીને ઉપર સ્વાઇપ કરો. સંકેતો વિશે વધુ જાણવા માટે ટૅપ કરો."</string> + <string name="overview_edu_notification_title" msgid="1265824157319562406">"તમારી તાજેતરની ઍપ જોવા માટે તમારા ટચપૅડનો ઉપયોગ કરો"</string> + <string name="overview_edu_notification_content" msgid="3578204677648432500">"ત્રણ આંગળીઓનો ઉપયોગ કરીને ઉપર સ્વાઇપ કરો અને દબાવી રાખો. સંકેતો વિશે વધુ જાણવા માટે ટૅપ કરો."</string> + <string name="all_apps_edu_notification_title" msgid="372262997265569063">"બધી ઍપ જોવા માટે તમારા કીબોર્ડનો ઉપયોગ કરો"</string> + <string name="all_apps_edu_notification_content" msgid="3255070575694025585">"કોઈપણ સમયે ઍક્શન કી દબાવો. સંકેતો વિશે વધુ જાણવા માટે ટૅપ કરો."</string> </resources> diff --git a/packages/SystemUI/res/values-gu/tiles_states_strings.xml b/packages/SystemUI/res/values-gu/tiles_states_strings.xml index 196a05bc4ed5..5c4a4784c13f 100644 --- a/packages/SystemUI/res/values-gu/tiles_states_strings.xml +++ b/packages/SystemUI/res/values-gu/tiles_states_strings.xml @@ -56,11 +56,6 @@ <item msgid="5376619709702103243">"બંધ છે"</item> <item msgid="4875147066469902392">"ચાલુ છે"</item> </string-array> - <string-array name="tile_states_modes"> - <item msgid="7764936419245199023">"અનુપલબ્ધ"</item> - <item msgid="2004750556637773692">"બંધ"</item> - <item msgid="8968530753931637871">"ચાલુ"</item> - </string-array> <string-array name="tile_states_flashlight"> <item msgid="3465257127433353857">"ઉપલબ્ધ નથી"</item> <item msgid="5044688398303285224">"બંધ છે"</item> diff --git a/packages/SystemUI/res/values-hi/strings.xml b/packages/SystemUI/res/values-hi/strings.xml index b3c861fb6ebe..6d9637612dd9 100644 --- a/packages/SystemUI/res/values-hi/strings.xml +++ b/packages/SystemUI/res/values-hi/strings.xml @@ -388,6 +388,9 @@ <string name="performance" msgid="6552785217174378320">"परफ़ॉर्मेंस"</string> <string name="user_interface" msgid="3712869377953950887">"यूज़र इंटरफ़ेस"</string> <string name="thermal" msgid="6758074791325414831">"थर्मल"</string> + <string name="custom" msgid="3337456985275158299">"कस्टम"</string> + <string name="custom_trace_settings_dialog_title" msgid="2608570500144830554">"कस्टम ट्रेस सेटिंग"</string> + <string name="restore_default" msgid="5259420807486239755">"डिफ़ॉल्ट सेटिंग वापस लाएं"</string> <string name="quick_settings_onehanded_label" msgid="2416537930246274991">"वन-हैंडेड मोड"</string> <string name="quick_settings_hearing_devices_label" msgid="7277170419679404129">"कान की मशीनें"</string> <string name="quick_settings_hearing_devices_connected" msgid="6519069502397037781">"ऐक्टिव"</string> @@ -431,6 +434,12 @@ <string name="zen_modes_dialog_settings" msgid="2310248023728936697">"सेटिंग"</string> <string name="zen_mode_on" msgid="9085304934016242591">"चालू है"</string> <string name="zen_mode_off" msgid="1736604456618147306">"बंद है"</string> + <!-- no translation found for zen_mode_set_up (7457957033034460064) --> + <skip /> + <!-- no translation found for zen_mode_no_manual_invocation (1769975741344633672) --> + <skip /> + <!-- no translation found for zen_mode_active_modes (1625850411578488856) --> + <skip /> <string name="zen_priority_introduction" msgid="3159291973383796646">"आपको अलार्म, रिमाइंडर, इवेंट और चुनिंदा कॉल करने वालों के अलावा किसी और तरह से (आवाज़ करके और थरथरा कर ) परेशान नहीं किया जाएगा. आप फिर भी संगीत, वीडियो और गेम सहित अपना चुना हुआ सब कुछ सुन सकते हैं."</string> <string name="zen_alarms_introduction" msgid="3987266042682300470">"आपको अलार्म छोड़कर दूसरी आवाज़ों और कंपनों से परेशान नहीं किया जाएगा. आपको अब भी संगीत, वीडियो और गेम सहित वह सब कुछ सुनाई देगा जो आपने चलाने के लिए चुना है."</string> <string name="zen_priority_customize_button" msgid="4119213187257195047">"अपनी पसंद के मुताबिक बनाएं"</string> @@ -469,6 +478,8 @@ <string name="keyguard_indication_charging_time_slowly" msgid="301936949731705417">"<xliff:g id="PERCENTAGE">%2$s</xliff:g> • धीरे चार्ज हो रहा है • <xliff:g id="CHARGING_TIME_LEFT">%1$s</xliff:g> में पूरा चार्ज हो जाएगा"</string> <string name="keyguard_indication_charging_time_dock" msgid="3149328898931741271">"<xliff:g id="PERCENTAGE">%2$s</xliff:g> • चार्ज हो रहा है • <xliff:g id="CHARGING_TIME_LEFT">%1$s</xliff:g> में पूरा चार्ज हो जाएगा"</string> <string name="accessibility_action_open_communal_hub" msgid="3081702792413787849">"लॉक स्क्रीन पर विजेट"</string> + <!-- no translation found for accessibility_announcement_communal_widget_added (6911593106099328271) --> + <skip /> <string name="communal_tutorial_indicator_text" msgid="4503010353591430123">"कम्यूनिटी ट्यूटोरियल शुरू करने के लिए, बाईं ओर स्वाइप करें"</string> <string name="cta_tile_button_to_open_widget_editor" msgid="3871562362382963878">"पसंद के मुताबिक बनाएं"</string> <string name="cta_tile_button_to_dismiss" msgid="3377597875997861754">"खारिज करें"</string> @@ -554,10 +565,8 @@ <string name="media_projection_action_text" msgid="3634906766918186440">"अभी शुरू करें"</string> <string name="empty_shade_text" msgid="8935967157319717412">"कोई सूचना नहीं है"</string> <string name="no_unseen_notif_text" msgid="395512586119868682">"कोई नई सूचना नहीं है"</string> - <!-- no translation found for adaptive_notification_edu_hun_title (7790738150177329960) --> - <skip /> - <!-- no translation found for adaptive_notification_edu_hun_text (7743367744129536610) --> - <skip /> + <string name="adaptive_notification_edu_hun_title" msgid="7790738150177329960">"नोटिफ़िकेशन कूलडाउन की सेटिंग चालू है"</string> + <string name="adaptive_notification_edu_hun_text" msgid="7743367744129536610">"एक साथ कई सूचनाएं मिलने पर, डिवाइस में सूचनाओं से होने वाली आवाज़ और सूचनाएं, दो मिनट के लिए अपने-आप कम हो जाएंगी."</string> <string name="go_to_adaptive_notification_settings" msgid="2423690125178298479">"बंद करें"</string> <string name="unlock_to_see_notif_text" msgid="7439033907167561227">"पुरानी सूचाएं देखने के लिए अनलॉक करें"</string> <string name="quick_settings_disclosure_parental_controls" msgid="2114102871438223600">"इस डिवाइस का प्रबंधन आपके अभिभावक करते हैं"</string> @@ -1223,7 +1232,6 @@ <string name="accessibility_fingerprint_bouncer" msgid="7189102492498735519">"पुष्टि करना ज़रूरी है. पुष्टि करने के लिए, फ़िंगरप्रिंट सेंसर को छुएं."</string> <string name="ongoing_phone_call_content_description" msgid="5332334388483099947">"फ़ोन कॉल चल रहा है"</string> <string name="mobile_data_settings_title" msgid="3955246641380064901">"मोबाइल डेटा"</string> - <string name="preference_summary_default_combination" msgid="8453246369903749670">"<xliff:g id="STATE">%1$s</xliff:g> / <xliff:g id="NETWORKMODE">%2$s</xliff:g>"</string> <string name="mobile_data_connection_active" msgid="944490013299018227">"कनेक्ट हो गया"</string> <string name="mobile_data_temp_connection_active" msgid="4590222725908806824">"इंटरनेट कनेक्शन कुछ समय के लिए है"</string> <string name="mobile_data_poor_connection" msgid="819617772268371434">"इंटरनेट कनेक्शन खराब है"</string> @@ -1377,7 +1385,10 @@ <string name="touchpad_tutorial_done_button" msgid="176168488821755503">"हो गया"</string> <string name="touchpad_tutorial_gesture_done" msgid="4784438360736821255">"बहुत बढ़िया!"</string> <string name="touchpad_back_gesture_action_title" msgid="7199067250654332735">"वापस जाएं"</string> - <string name="touchpad_back_gesture_guidance" msgid="4222430588599527272">"वापस जाने के लिए, टचपैड पर कहीं भी तीन उंगलियों से बाईं या दाईं तरफ़ स्वाइप करें."</string> + <!-- no translation found for touchpad_back_gesture_guidance (6263750214998421587) --> + <skip /> + <!-- no translation found for touchpad_back_gesture_finished (5353616006999726249) --> + <skip /> <string name="touchpad_back_gesture_animation_content_description" msgid="2646107450922379918">"टचपैड पर तीन उंगलियों को दाईं और बाईं तरफ़ ले जाया जा रहा है"</string> <string name="touchpad_back_gesture_screen_animation_content_description" msgid="4036267494237748710">"डिवाइस की स्क्रीन पर, पिछले पेज पर जाने के लिए हाथ के जेस्चर का ऐनिमेशन दिख रहा है"</string> <string name="keyboard_backlight_dialog_title" msgid="8273102932345564724">"कीबोर्ड की बैकलाइट"</string> diff --git a/packages/SystemUI/res/values-hi/tiles_states_strings.xml b/packages/SystemUI/res/values-hi/tiles_states_strings.xml index b988d727b85d..b89eeb3c0f0f 100644 --- a/packages/SystemUI/res/values-hi/tiles_states_strings.xml +++ b/packages/SystemUI/res/values-hi/tiles_states_strings.xml @@ -56,11 +56,6 @@ <item msgid="5376619709702103243">"बंद है"</item> <item msgid="4875147066469902392">"चालू है"</item> </string-array> - <string-array name="tile_states_modes"> - <item msgid="7764936419245199023">"उपलब्ध नहीं है"</item> - <item msgid="2004750556637773692">"बंद है"</item> - <item msgid="8968530753931637871">"चालू है"</item> - </string-array> <string-array name="tile_states_flashlight"> <item msgid="3465257127433353857">"उपलब्ध नहीं है"</item> <item msgid="5044688398303285224">"बंद है"</item> diff --git a/packages/SystemUI/res/values-hr/strings.xml b/packages/SystemUI/res/values-hr/strings.xml index 3bd6c64aa3cc..1d5051c3d5d1 100644 --- a/packages/SystemUI/res/values-hr/strings.xml +++ b/packages/SystemUI/res/values-hr/strings.xml @@ -388,6 +388,9 @@ <string name="performance" msgid="6552785217174378320">"Izvedba"</string> <string name="user_interface" msgid="3712869377953950887">"Korisničko sučelje"</string> <string name="thermal" msgid="6758074791325414831">"Termalno"</string> + <string name="custom" msgid="3337456985275158299">"Prilagođeno"</string> + <string name="custom_trace_settings_dialog_title" msgid="2608570500144830554">"Postavke prilagođenog praćenja"</string> + <string name="restore_default" msgid="5259420807486239755">"Vrati na zadano"</string> <string name="quick_settings_onehanded_label" msgid="2416537930246274991">"Način rada jednom rukom"</string> <string name="quick_settings_hearing_devices_label" msgid="7277170419679404129">"Slušna pomagala"</string> <string name="quick_settings_hearing_devices_connected" msgid="6519069502397037781">"Aktivno"</string> @@ -429,9 +432,13 @@ <string name="zen_modes_dialog_title" msgid="4159138230418567383">"Prioritetni načini"</string> <string name="zen_modes_dialog_done" msgid="6654130880256438950">"Gotovo"</string> <string name="zen_modes_dialog_settings" msgid="2310248023728936697">"Postavke"</string> - <!-- no translation found for zen_mode_on (9085304934016242591) --> + <string name="zen_mode_on" msgid="9085304934016242591">"Uključeno"</string> + <string name="zen_mode_off" msgid="1736604456618147306">"Isključeno"</string> + <!-- no translation found for zen_mode_set_up (7457957033034460064) --> <skip /> - <!-- no translation found for zen_mode_off (1736604456618147306) --> + <!-- no translation found for zen_mode_no_manual_invocation (1769975741344633672) --> + <skip /> + <!-- no translation found for zen_mode_active_modes (1625850411578488856) --> <skip /> <string name="zen_priority_introduction" msgid="3159291973383796646">"Neće vas ometati zvukovi i vibracije, osim alarma, podsjetnika, događaja i pozivatelja koje navedete. I dalje ćete čuti sve što želite reproducirati, uključujući glazbu, videozapise i igre."</string> <string name="zen_alarms_introduction" msgid="3987266042682300470">"Neće vas ometati zvukovi i vibracije, osim alarma. I dalje ćete čuti sve što želite reproducirati, uključujući glazbu, videozapise i igre."</string> @@ -471,6 +478,8 @@ <string name="keyguard_indication_charging_time_slowly" msgid="301936949731705417">"<xliff:g id="PERCENTAGE">%2$s</xliff:g> • sporo punjenje • <xliff:g id="CHARGING_TIME_LEFT">%1$s</xliff:g> do napunjenosti"</string> <string name="keyguard_indication_charging_time_dock" msgid="3149328898931741271">"<xliff:g id="PERCENTAGE">%2$s</xliff:g> • punjenje • <xliff:g id="CHARGING_TIME_LEFT">%1$s</xliff:g> do napunjenosti"</string> <string name="accessibility_action_open_communal_hub" msgid="3081702792413787849">"Widgeti na zaključanom zaslonu"</string> + <!-- no translation found for accessibility_announcement_communal_widget_added (6911593106099328271) --> + <skip /> <string name="communal_tutorial_indicator_text" msgid="4503010353591430123">"Prijeđite prstom ulijevo da biste pokrenuli zajednički vodič"</string> <string name="cta_tile_button_to_open_widget_editor" msgid="3871562362382963878">"Prilagodi"</string> <string name="cta_tile_button_to_dismiss" msgid="3377597875997861754">"Odbaci"</string> @@ -499,8 +508,7 @@ <string name="accessibility_action_label_place_widget" msgid="1914197458644168978">"postavi odabrani widget"</string> <string name="communal_widget_picker_title" msgid="1953369090475731663">"Widgeti zaključanog zaslona"</string> <string name="communal_widget_picker_description" msgid="490515450110487871">"Svi vide widgete na vašem zaključanom zaslonu, čak i ako je tablet zaključan."</string> - <!-- no translation found for accessibility_action_label_unselect_widget (1041811747619468698) --> - <skip /> + <string name="accessibility_action_label_unselect_widget" msgid="1041811747619468698">"poništavanje odabira widgeta"</string> <string name="communal_widgets_disclaimer_title" msgid="1150954395585308868">"Widgeti na zaključanom zaslonu"</string> <string name="communal_widgets_disclaimer_text" msgid="1423545475160506349">"Da biste otvorili aplikaciju pomoću widgeta, trebate potvrditi da ste to vi. Također napominjemo da ih svatko može vidjeti, čak i ako je vaš tablet zaključan. Neki widgeti možda nisu namijenjeni za zaključani zaslon, pa ih možda nije sigurno dodati ovdje."</string> <string name="communal_widgets_disclaimer_button" msgid="4423059765740780753">"Shvaćam"</string> @@ -557,10 +565,8 @@ <string name="media_projection_action_text" msgid="3634906766918186440">"Pokreni"</string> <string name="empty_shade_text" msgid="8935967157319717412">"Nema obavijesti"</string> <string name="no_unseen_notif_text" msgid="395512586119868682">"Nema novih obavijesti"</string> - <!-- no translation found for adaptive_notification_edu_hun_title (7790738150177329960) --> - <skip /> - <!-- no translation found for adaptive_notification_edu_hun_text (7743367744129536610) --> - <skip /> + <string name="adaptive_notification_edu_hun_title" msgid="7790738150177329960">"Stišavanje obavijesti je uključeno"</string> + <string name="adaptive_notification_edu_hun_text" msgid="7743367744129536610">"Glasnoća/upozorenja uređaja automatski se stišavaju do 2 min kad primite previše obavijesti odjednom"</string> <string name="go_to_adaptive_notification_settings" msgid="2423690125178298479">"Isključi"</string> <string name="unlock_to_see_notif_text" msgid="7439033907167561227">"Otključajte za starije obavijesti"</string> <string name="quick_settings_disclosure_parental_controls" msgid="2114102871438223600">"Ovim uređajem upravlja tvoj roditelj"</string> @@ -1226,7 +1232,6 @@ <string name="accessibility_fingerprint_bouncer" msgid="7189102492498735519">"Potrebna je autentifikacija. Dodirnite senzor otiska prsta da biste se autentificirali."</string> <string name="ongoing_phone_call_content_description" msgid="5332334388483099947">"Telefonski poziv u tijeku"</string> <string name="mobile_data_settings_title" msgid="3955246641380064901">"Mobilni podaci"</string> - <string name="preference_summary_default_combination" msgid="8453246369903749670">"<xliff:g id="STATE">%1$s</xliff:g>/<xliff:g id="NETWORKMODE">%2$s</xliff:g>"</string> <string name="mobile_data_connection_active" msgid="944490013299018227">"Povezano"</string> <string name="mobile_data_temp_connection_active" msgid="4590222725908806824">"Privremeno povezano"</string> <string name="mobile_data_poor_connection" msgid="819617772268371434">"Slaba veza"</string> @@ -1380,7 +1385,10 @@ <string name="touchpad_tutorial_done_button" msgid="176168488821755503">"Gotovo"</string> <string name="touchpad_tutorial_gesture_done" msgid="4784438360736821255">"Sjajno!"</string> <string name="touchpad_back_gesture_action_title" msgid="7199067250654332735">"Natrag"</string> - <string name="touchpad_back_gesture_guidance" msgid="4222430588599527272">"Za povratak trima prstima prijeđite ulijevo ili udesno bilo gdje na dodirnoj podlozi."</string> + <!-- no translation found for touchpad_back_gesture_guidance (6263750214998421587) --> + <skip /> + <!-- no translation found for touchpad_back_gesture_finished (5353616006999726249) --> + <skip /> <string name="touchpad_back_gesture_animation_content_description" msgid="2646107450922379918">"Dodirna podloga prikazuje tri prsta koji se kreću udesno i ulijevo"</string> <string name="touchpad_back_gesture_screen_animation_content_description" msgid="4036267494237748710">"Na zaslonu uređaja prikazuje se animacija za pokret za povratak"</string> <string name="keyboard_backlight_dialog_title" msgid="8273102932345564724">"Pozadinsko osvjetljenje tipkovnice"</string> @@ -1388,28 +1396,16 @@ <string name="home_controls_dream_label" msgid="6567105701292324257">"Upravljanje uređajima"</string> <string name="home_controls_dream_description" msgid="4644150952104035789">"Brzo upravljajte uređajima putem čuvara zaslona"</string> <string name="volume_undo_action" msgid="5815519725211877114">"Poništi"</string> - <!-- no translation found for back_edu_toast_content (4530314597378982956) --> - <skip /> - <!-- no translation found for home_edu_toast_content (3381071147871955415) --> - <skip /> - <!-- no translation found for overview_edu_toast_content (5797030644017804518) --> - <skip /> - <!-- no translation found for all_apps_edu_toast_content (8807496014667211562) --> - <skip /> - <!-- no translation found for back_edu_notification_title (5624780717751357278) --> - <skip /> - <!-- no translation found for back_edu_notification_content (2497557451540954068) --> - <skip /> - <!-- no translation found for home_edu_notification_title (6097902076909654045) --> - <skip /> - <!-- no translation found for home_edu_notification_content (6631697734535766588) --> - <skip /> - <!-- no translation found for overview_edu_notification_title (1265824157319562406) --> - <skip /> - <!-- no translation found for overview_edu_notification_content (3578204677648432500) --> - <skip /> - <!-- no translation found for all_apps_edu_notification_title (372262997265569063) --> - <skip /> - <!-- no translation found for all_apps_edu_notification_content (3255070575694025585) --> - <skip /> + <string name="back_edu_toast_content" msgid="4530314597378982956">"Za povratak prijeđite ulijevo ili udesno trima prstima na dodirnoj podlozi"</string> + <string name="home_edu_toast_content" msgid="3381071147871955415">"Da biste se vratili na početni zaslon, prijeđite prema gore trima prstima na dodirnoj podlozi."</string> + <string name="overview_edu_toast_content" msgid="5797030644017804518">"Za prikaz nedavnih aplikacija prijeđite prema gore trima prstima i zadržite pritisak na dodirnoj podlozi"</string> + <string name="all_apps_edu_toast_content" msgid="8807496014667211562">"Za prikaz svojih svih aplikacija pritisnite tipku za radnju na tipkovnici"</string> + <string name="back_edu_notification_title" msgid="5624780717751357278">"Upotrijebite dodirnu podlogu za povratak"</string> + <string name="back_edu_notification_content" msgid="2497557451540954068">"Prijeđite ulijevo ili udesno trima prstima. Dodirnite da biste naučili više pokreta."</string> + <string name="home_edu_notification_title" msgid="6097902076909654045">"Uz pomoć dodirne podloge vratite se na početni zaslon"</string> + <string name="home_edu_notification_content" msgid="6631697734535766588">"Prijeđite prema gore trima prstima. Dodirnite da biste naučili više pokreta."</string> + <string name="overview_edu_notification_title" msgid="1265824157319562406">"Upotrijebite dodirnu podlogu za prikaz nedavnih aplikacija"</string> + <string name="overview_edu_notification_content" msgid="3578204677648432500">"Prijeđite prema gore trima prstima i zadržite pritisak. Dodirnite da biste naučili više pokreta."</string> + <string name="all_apps_edu_notification_title" msgid="372262997265569063">"Upotrijebite tipkovnicu za prikaz svih aplikacija"</string> + <string name="all_apps_edu_notification_content" msgid="3255070575694025585">"Pritisnite tipku za radnju u bilo kojem trenutku. Dodirnite da biste naučili više pokreta."</string> </resources> diff --git a/packages/SystemUI/res/values-hr/tiles_states_strings.xml b/packages/SystemUI/res/values-hr/tiles_states_strings.xml index be48b3bcb916..df0b78664cba 100644 --- a/packages/SystemUI/res/values-hr/tiles_states_strings.xml +++ b/packages/SystemUI/res/values-hr/tiles_states_strings.xml @@ -56,11 +56,6 @@ <item msgid="5376619709702103243">"Isključeno"</item> <item msgid="4875147066469902392">"Uključeno"</item> </string-array> - <string-array name="tile_states_modes"> - <item msgid="7764936419245199023">"Nedostupno"</item> - <item msgid="2004750556637773692">"Isključeno"</item> - <item msgid="8968530753931637871">"Uključeno"</item> - </string-array> <string-array name="tile_states_flashlight"> <item msgid="3465257127433353857">"Nedostupno"</item> <item msgid="5044688398303285224">"Isključeno"</item> diff --git a/packages/SystemUI/res/values-hu/strings.xml b/packages/SystemUI/res/values-hu/strings.xml index 7a0325e3c658..06040645840d 100644 --- a/packages/SystemUI/res/values-hu/strings.xml +++ b/packages/SystemUI/res/values-hu/strings.xml @@ -388,6 +388,9 @@ <string name="performance" msgid="6552785217174378320">"Teljesítmény"</string> <string name="user_interface" msgid="3712869377953950887">"Kezelőfelület"</string> <string name="thermal" msgid="6758074791325414831">"Termikus"</string> + <string name="custom" msgid="3337456985275158299">"Egyéni"</string> + <string name="custom_trace_settings_dialog_title" msgid="2608570500144830554">"Egyéni nyombeállítások"</string> + <string name="restore_default" msgid="5259420807486239755">"Alapértelmezett érték visszaállítása"</string> <string name="quick_settings_onehanded_label" msgid="2416537930246274991">"Egykezes mód"</string> <string name="quick_settings_hearing_devices_label" msgid="7277170419679404129">"Hallókészülékek"</string> <string name="quick_settings_hearing_devices_connected" msgid="6519069502397037781">"Aktív"</string> @@ -429,9 +432,13 @@ <string name="zen_modes_dialog_title" msgid="4159138230418567383">"Prioritási módok"</string> <string name="zen_modes_dialog_done" msgid="6654130880256438950">"Kész"</string> <string name="zen_modes_dialog_settings" msgid="2310248023728936697">"Beállítások"</string> - <!-- no translation found for zen_mode_on (9085304934016242591) --> + <string name="zen_mode_on" msgid="9085304934016242591">"Be"</string> + <string name="zen_mode_off" msgid="1736604456618147306">"Ki"</string> + <!-- no translation found for zen_mode_set_up (7457957033034460064) --> <skip /> - <!-- no translation found for zen_mode_off (1736604456618147306) --> + <!-- no translation found for zen_mode_no_manual_invocation (1769975741344633672) --> + <skip /> + <!-- no translation found for zen_mode_active_modes (1625850411578488856) --> <skip /> <string name="zen_priority_introduction" msgid="3159291973383796646">"Az Ön által meghatározott ébresztéseken, emlékeztetőkön, eseményeken és hívókon kívül nem fogja Önt más hang vagy rezgés megzavarni. Továbbra is lesz hangjuk azoknak a tartalmaknak, amelyeket Ön elindít, például zenék, videók és játékok."</string> <string name="zen_alarms_introduction" msgid="3987266042682300470">"Az ébresztéseken kívül nem fogja Önt más hang és rezgés megzavarni. Továbbra is lesz hangjuk azoknak a tartalmaknak, amelyeket Ön elindít, például zenék, videók és játékok."</string> @@ -471,6 +478,8 @@ <string name="keyguard_indication_charging_time_slowly" msgid="301936949731705417">"<xliff:g id="PERCENTAGE">%2$s</xliff:g> • Lassú töltés • A teljes töltöttségig: <xliff:g id="CHARGING_TIME_LEFT">%1$s</xliff:g>"</string> <string name="keyguard_indication_charging_time_dock" msgid="3149328898931741271">"<xliff:g id="PERCENTAGE">%2$s</xliff:g> • Töltés • A teljes töltöttségig: <xliff:g id="CHARGING_TIME_LEFT">%1$s</xliff:g>"</string> <string name="accessibility_action_open_communal_hub" msgid="3081702792413787849">"Modulok a lezárási képernyőn"</string> + <!-- no translation found for accessibility_announcement_communal_widget_added (6911593106099328271) --> + <skip /> <string name="communal_tutorial_indicator_text" msgid="4503010353591430123">"Csúsztasson gyorsan balra a közösségi útmutató elindításához"</string> <string name="cta_tile_button_to_open_widget_editor" msgid="3871562362382963878">"Személyre szabás"</string> <string name="cta_tile_button_to_dismiss" msgid="3377597875997861754">"Elvetés"</string> @@ -499,8 +508,7 @@ <string name="accessibility_action_label_place_widget" msgid="1914197458644168978">"kijelölt modul áthelyezése"</string> <string name="communal_widget_picker_title" msgid="1953369090475731663">"A lezárási képernyő moduljai"</string> <string name="communal_widget_picker_description" msgid="490515450110487871">"Bárki megtekintheti a modulokat a lezárási képernyőjén, még ha a táblagépe zárolva is van."</string> - <!-- no translation found for accessibility_action_label_unselect_widget (1041811747619468698) --> - <skip /> + <string name="accessibility_action_label_unselect_widget" msgid="1041811747619468698">"modul kijelölésének megszüntetése"</string> <string name="communal_widgets_disclaimer_title" msgid="1150954395585308868">"A lezárási képernyő moduljai"</string> <string name="communal_widgets_disclaimer_text" msgid="1423545475160506349">"Ha modul használatával szeretne megnyitni egy alkalmazást, igazolnia kell a személyazonosságát. Ne felejtse továbbá, hogy bárki megtekintheti a modulokat, még akkor is, amikor zárolva van a táblagép. Előfordulhat, hogy bizonyos modulokat nem a lezárási képernyőn való használatra terveztek, ezért nem biztonságos a hozzáadásuk."</string> <string name="communal_widgets_disclaimer_button" msgid="4423059765740780753">"Értem"</string> @@ -557,10 +565,8 @@ <string name="media_projection_action_text" msgid="3634906766918186440">"Indítás most"</string> <string name="empty_shade_text" msgid="8935967157319717412">"Nincs értesítés"</string> <string name="no_unseen_notif_text" msgid="395512586119868682">"Nincsenek új értesítések"</string> - <!-- no translation found for adaptive_notification_edu_hun_title (7790738150177329960) --> - <skip /> - <!-- no translation found for adaptive_notification_edu_hun_text (7743367744129536610) --> - <skip /> + <string name="adaptive_notification_edu_hun_title" msgid="7790738150177329960">"Értesítések befagyasztása bekapcsolva"</string> + <string name="adaptive_notification_edu_hun_text" msgid="7743367744129536610">"Az eszköz hangerejét és értesítéseit a rendszer automatikusan legfeljebb két percig csökkenti, ha egyszerre túl sok értesítést kap."</string> <string name="go_to_adaptive_notification_settings" msgid="2423690125178298479">"Igen"</string> <string name="unlock_to_see_notif_text" msgid="7439033907167561227">"A régebbiek feloldás után láthatók"</string> <string name="quick_settings_disclosure_parental_controls" msgid="2114102871438223600">"Az eszközt a szülőd felügyeli"</string> @@ -1226,7 +1232,6 @@ <string name="accessibility_fingerprint_bouncer" msgid="7189102492498735519">"Hitelesítés szükséges. Érintse meg az ujjlenyomat-érzékelőt a hitelesítéshez."</string> <string name="ongoing_phone_call_content_description" msgid="5332334388483099947">"Folyamatban lévő telefonhívás"</string> <string name="mobile_data_settings_title" msgid="3955246641380064901">"Mobiladat"</string> - <string name="preference_summary_default_combination" msgid="8453246369903749670">"<xliff:g id="NETWORKMODE">%2$s</xliff:g>/<xliff:g id="STATE">%1$s</xliff:g>"</string> <string name="mobile_data_connection_active" msgid="944490013299018227">"Csatlakozva"</string> <string name="mobile_data_temp_connection_active" msgid="4590222725908806824">"Ideiglenesen csatlakoztatva"</string> <string name="mobile_data_poor_connection" msgid="819617772268371434">"Gyenge kapcsolat"</string> @@ -1380,7 +1385,10 @@ <string name="touchpad_tutorial_done_button" msgid="176168488821755503">"Kész"</string> <string name="touchpad_tutorial_gesture_done" msgid="4784438360736821255">"Kiváló!"</string> <string name="touchpad_back_gesture_action_title" msgid="7199067250654332735">"Vissza"</string> - <string name="touchpad_back_gesture_guidance" msgid="4222430588599527272">"A visszalépéshez csúsztasson három ujjal gyorsan balra vagy a jobbra az érintőpad tetszőleges területén."</string> + <!-- no translation found for touchpad_back_gesture_guidance (6263750214998421587) --> + <skip /> + <!-- no translation found for touchpad_back_gesture_finished (5353616006999726249) --> + <skip /> <string name="touchpad_back_gesture_animation_content_description" msgid="2646107450922379918">"Három, jobbra és balra mozgó ujjat ábrázoló érintőpad"</string> <string name="touchpad_back_gesture_screen_animation_content_description" msgid="4036267494237748710">"A Vissza kézmozdulat animációját megjelenítő eszközképernyő"</string> <string name="keyboard_backlight_dialog_title" msgid="8273102932345564724">"A billentyűzet háttérvilágítása"</string> @@ -1388,28 +1396,16 @@ <string name="home_controls_dream_label" msgid="6567105701292324257">"Otthon vezérlése"</string> <string name="home_controls_dream_description" msgid="4644150952104035789">"Gyorsan vezérelheti otthonát képernyőkímélővel"</string> <string name="volume_undo_action" msgid="5815519725211877114">"Visszavonás"</string> - <!-- no translation found for back_edu_toast_content (4530314597378982956) --> - <skip /> - <!-- no translation found for home_edu_toast_content (3381071147871955415) --> - <skip /> - <!-- no translation found for overview_edu_toast_content (5797030644017804518) --> - <skip /> - <!-- no translation found for all_apps_edu_toast_content (8807496014667211562) --> - <skip /> - <!-- no translation found for back_edu_notification_title (5624780717751357278) --> - <skip /> - <!-- no translation found for back_edu_notification_content (2497557451540954068) --> - <skip /> - <!-- no translation found for home_edu_notification_title (6097902076909654045) --> - <skip /> - <!-- no translation found for home_edu_notification_content (6631697734535766588) --> - <skip /> - <!-- no translation found for overview_edu_notification_title (1265824157319562406) --> - <skip /> - <!-- no translation found for overview_edu_notification_content (3578204677648432500) --> - <skip /> - <!-- no translation found for all_apps_edu_notification_title (372262997265569063) --> - <skip /> - <!-- no translation found for all_apps_edu_notification_content (3255070575694025585) --> - <skip /> + <string name="back_edu_toast_content" msgid="4530314597378982956">"A visszalépéshez csúsztasson három ujjal balra vagy a jobbra az érintőpadon."</string> + <string name="home_edu_toast_content" msgid="3381071147871955415">"A kezdőképernyőre való ugráshoz csúsztasson felfelé három ujjal az érintőpadon."</string> + <string name="overview_edu_toast_content" msgid="5797030644017804518">"A legutóbbi appokért csúsztasson lefelé három ujjal az érintőpadon, és tartsa lenyomva ujjait."</string> + <string name="all_apps_edu_toast_content" msgid="8807496014667211562">"Az összes alkalmazás megtekintéséhez nyomja meg a billentyűzet műveletbillentyűjét."</string> + <string name="back_edu_notification_title" msgid="5624780717751357278">"A visszalépéshez használja az érintőpadot"</string> + <string name="back_edu_notification_content" msgid="2497557451540954068">"Csúsztatasson gyorsan három ujjal balra vagy jobbra. Koppintson a további kézmozdulatokért."</string> + <string name="home_edu_notification_title" msgid="6097902076909654045">"A kezdőképernyő megnyitásához használja az érintőpadot"</string> + <string name="home_edu_notification_content" msgid="6631697734535766588">"Túsztasson felfelé három ujjal. Koppintson a további kézmozdulatokért."</string> + <string name="overview_edu_notification_title" msgid="1265824157319562406">"A legutóbbi alkalmazások megtekintéséhez használja az érintőpadot"</string> + <string name="overview_edu_notification_content" msgid="3578204677648432500">"Gyúsztason felfelé három ujjal, és tartsa lenyomva az ujjait. Koppintson a további kézmozdulatokért."</string> + <string name="all_apps_edu_notification_title" msgid="372262997265569063">"A billentyűzet használatával valamennyi alkalmazás megtekinthető"</string> + <string name="all_apps_edu_notification_content" msgid="3255070575694025585">"A műveletbillentyű bármikor használható. Koppintson a további kézmozdulatokért."</string> </resources> diff --git a/packages/SystemUI/res/values-hu/tiles_states_strings.xml b/packages/SystemUI/res/values-hu/tiles_states_strings.xml index ef23a29b195c..bbd6bc0ebbbb 100644 --- a/packages/SystemUI/res/values-hu/tiles_states_strings.xml +++ b/packages/SystemUI/res/values-hu/tiles_states_strings.xml @@ -56,11 +56,6 @@ <item msgid="5376619709702103243">"Ki"</item> <item msgid="4875147066469902392">"Be"</item> </string-array> - <string-array name="tile_states_modes"> - <item msgid="7764936419245199023">"Nem áll rendelkezésre"</item> - <item msgid="2004750556637773692">"Ki"</item> - <item msgid="8968530753931637871">"Be"</item> - </string-array> <string-array name="tile_states_flashlight"> <item msgid="3465257127433353857">"Nem áll rendelkezésre"</item> <item msgid="5044688398303285224">"Ki"</item> diff --git a/packages/SystemUI/res/values-hy/strings.xml b/packages/SystemUI/res/values-hy/strings.xml index afe79208f395..6f32125456b0 100644 --- a/packages/SystemUI/res/values-hy/strings.xml +++ b/packages/SystemUI/res/values-hy/strings.xml @@ -388,6 +388,9 @@ <string name="performance" msgid="6552785217174378320">"Արդյունավետություն"</string> <string name="user_interface" msgid="3712869377953950887">"Օգտատիրական ինտերֆեյս"</string> <string name="thermal" msgid="6758074791325414831">"Ջերմատեսիլ"</string> + <string name="custom" msgid="3337456985275158299">"Հատուկ"</string> + <string name="custom_trace_settings_dialog_title" msgid="2608570500144830554">"Հետագծման հատուկ կարգավորումներ"</string> + <string name="restore_default" msgid="5259420807486239755">"Վերականգնել կանխադրված կարգավորումները"</string> <string name="quick_settings_onehanded_label" msgid="2416537930246274991">"Մեկ ձեռքի ռեժիմ"</string> <string name="quick_settings_hearing_devices_label" msgid="7277170419679404129">"Լսողական սարքեր"</string> <string name="quick_settings_hearing_devices_connected" msgid="6519069502397037781">"Ակտիվ է"</string> @@ -429,9 +432,13 @@ <string name="zen_modes_dialog_title" msgid="4159138230418567383">"Կարևոր ռեժիմներ"</string> <string name="zen_modes_dialog_done" msgid="6654130880256438950">"Պատրաստ է"</string> <string name="zen_modes_dialog_settings" msgid="2310248023728936697">"Կարգավորումներ"</string> - <!-- no translation found for zen_mode_on (9085304934016242591) --> + <string name="zen_mode_on" msgid="9085304934016242591">"Միացված է"</string> + <string name="zen_mode_off" msgid="1736604456618147306">"Անջատված է"</string> + <!-- no translation found for zen_mode_set_up (7457957033034460064) --> <skip /> - <!-- no translation found for zen_mode_off (1736604456618147306) --> + <!-- no translation found for zen_mode_no_manual_invocation (1769975741344633672) --> + <skip /> + <!-- no translation found for zen_mode_active_modes (1625850411578488856) --> <skip /> <string name="zen_priority_introduction" msgid="3159291973383796646">"Ձայները և թրթռոցները չեն անհանգստացնի ձեզ, բացի ձեր կողմից նշված զարթուցիչները, հիշեցումները, միջոցառումների ծանուցումները և զանգերը։ Դուք կլսեք ձեր ընտրածի նվագարկումը, այդ թվում՝ երաժշտություն, տեսանյութեր և խաղեր:"</string> <string name="zen_alarms_introduction" msgid="3987266042682300470">"Ձայները և թրթռոցները, բացի զարթուցիչներից, չեն անհանգստացնի ձեզ: Դուք կլսեք ձեր ընտրածի նվագարկումը, այդ թվում՝ երաժշտություն, տեսանյութեր և խաղեր:"</string> @@ -471,6 +478,8 @@ <string name="keyguard_indication_charging_time_slowly" msgid="301936949731705417">"<xliff:g id="PERCENTAGE">%2$s</xliff:g> • Դանդաղ լիցքավորում • Մնացել է <xliff:g id="CHARGING_TIME_LEFT">%1$s</xliff:g>"</string> <string name="keyguard_indication_charging_time_dock" msgid="3149328898931741271">"<xliff:g id="PERCENTAGE">%2$s</xliff:g> • Լիցքավորում • Մնացել է <xliff:g id="CHARGING_TIME_LEFT">%1$s</xliff:g>"</string> <string name="accessibility_action_open_communal_hub" msgid="3081702792413787849">"Վիջեթներ կողպէկրանին"</string> + <!-- no translation found for accessibility_announcement_communal_widget_added (6911593106099328271) --> + <skip /> <string name="communal_tutorial_indicator_text" msgid="4503010353591430123">"Թերթեք ձախ՝ ուղեցույցը գործարկելու համար"</string> <string name="cta_tile_button_to_open_widget_editor" msgid="3871562362382963878">"Անհատականացնել"</string> <string name="cta_tile_button_to_dismiss" msgid="3377597875997861754">"Փակել"</string> @@ -499,8 +508,7 @@ <string name="accessibility_action_label_place_widget" msgid="1914197458644168978">"տեղադրել ընտրված վիջեթը"</string> <string name="communal_widget_picker_title" msgid="1953369090475731663">"Կողպէկրանի վիջեթներ"</string> <string name="communal_widget_picker_description" msgid="490515450110487871">"Բոլորը կարող են դիտել ձեր կողպէկրանի վիջեթները, նույնիսկ եթե պլանշետը կողպված է"</string> - <!-- no translation found for accessibility_action_label_unselect_widget (1041811747619468698) --> - <skip /> + <string name="accessibility_action_label_unselect_widget" msgid="1041811747619468698">"չեղարկել վիջեթի ընտրությունը"</string> <string name="communal_widgets_disclaimer_title" msgid="1150954395585308868">"Կողպէկրանի վիջեթներ"</string> <string name="communal_widgets_disclaimer_text" msgid="1423545475160506349">"Վիջեթի միջոցով հավելված բացելու համար դուք պետք է հաստատեք ձեր ինքնությունը։ Նաև նկատի ունեցեք, որ ցանկացած ոք կարող է դիտել վիջեթները, նույնիսկ երբ ձեր պլանշետը կողպված է։ Որոշ վիջեթներ կարող են նախատեսված չլինել ձեր կողպէկրանի համար, և այստեղ դրանց ավելացնելը կարող է վտանգավոր լինել։"</string> <string name="communal_widgets_disclaimer_button" msgid="4423059765740780753">"Եղավ"</string> @@ -557,10 +565,8 @@ <string name="media_projection_action_text" msgid="3634906766918186440">"Սկսել հիմա"</string> <string name="empty_shade_text" msgid="8935967157319717412">"Ծանուցումներ չկան"</string> <string name="no_unseen_notif_text" msgid="395512586119868682">"Նոր ծանուցումներ չկան"</string> - <!-- no translation found for adaptive_notification_edu_hun_title (7790738150177329960) --> - <skip /> - <!-- no translation found for adaptive_notification_edu_hun_text (7743367744129536610) --> - <skip /> + <string name="adaptive_notification_edu_hun_title" msgid="7790738150177329960">"Ծանուցումների ձայնի իջեցումը միացված է"</string> + <string name="adaptive_notification_edu_hun_text" msgid="7743367744129536610">"Սարքի և ծանուցումների ձայնն ավտոմատ իջեցվում է մինչև 2 րոպե, երբ շատ ծանուցումներ եք ստանում։"</string> <string name="go_to_adaptive_notification_settings" msgid="2423690125178298479">"Անջատել"</string> <string name="unlock_to_see_notif_text" msgid="7439033907167561227">"Ապակողպեք՝ տեսնելու հին ծանուցումները"</string> <string name="quick_settings_disclosure_parental_controls" msgid="2114102871438223600">"Այս սարքը կառավարում է ձեր ծնողը"</string> @@ -1226,7 +1232,6 @@ <string name="accessibility_fingerprint_bouncer" msgid="7189102492498735519">"Պահանջվում է նույնականացում։ Դրա համար մատը հպեք մատնահետքի սկաներին։"</string> <string name="ongoing_phone_call_content_description" msgid="5332334388483099947">"Ընթացիկ հեռախոսազանգ"</string> <string name="mobile_data_settings_title" msgid="3955246641380064901">"Բջջային ինտերնետ"</string> - <string name="preference_summary_default_combination" msgid="8453246369903749670">"<xliff:g id="STATE">%1$s</xliff:g>/<xliff:g id="NETWORKMODE">%2$s</xliff:g>"</string> <string name="mobile_data_connection_active" msgid="944490013299018227">"Միացած է"</string> <string name="mobile_data_temp_connection_active" msgid="4590222725908806824">"Ժամանակավոր կապ"</string> <string name="mobile_data_poor_connection" msgid="819617772268371434">"Թույլ կապ"</string> @@ -1380,7 +1385,10 @@ <string name="touchpad_tutorial_done_button" msgid="176168488821755503">"Պատրաստ է"</string> <string name="touchpad_tutorial_gesture_done" msgid="4784438360736821255">"Կեցցե՛ք"</string> <string name="touchpad_back_gesture_action_title" msgid="7199067250654332735">"Հետ գնալ"</string> - <string name="touchpad_back_gesture_guidance" msgid="4222430588599527272">"Հետ գնալու համար հպահարթակի վրա երեք մատով սահեցրեք ձախ կամ աջ։"</string> + <!-- no translation found for touchpad_back_gesture_guidance (6263750214998421587) --> + <skip /> + <!-- no translation found for touchpad_back_gesture_finished (5353616006999726249) --> + <skip /> <string name="touchpad_back_gesture_animation_content_description" msgid="2646107450922379918">"Երեք մատները աջ ու ձախ են շարժվում հպահարթակի վրա"</string> <string name="touchpad_back_gesture_screen_animation_content_description" msgid="4036267494237748710">"Սարքի էկրանին ցուցադրվում է շարժանկար՝ հետ գնալու ժեստի համար"</string> <string name="keyboard_backlight_dialog_title" msgid="8273102932345564724">"Հետին լուսավորությամբ ստեղնաշար"</string> @@ -1388,28 +1396,16 @@ <string name="home_controls_dream_label" msgid="6567105701292324257">"Տան կառավարման տարրեր"</string> <string name="home_controls_dream_description" msgid="4644150952104035789">"Տան կառավարման տարրերը դարձրեք էկրանապահ"</string> <string name="volume_undo_action" msgid="5815519725211877114">"Հետարկել"</string> - <!-- no translation found for back_edu_toast_content (4530314597378982956) --> - <skip /> - <!-- no translation found for home_edu_toast_content (3381071147871955415) --> - <skip /> - <!-- no translation found for overview_edu_toast_content (5797030644017804518) --> - <skip /> - <!-- no translation found for all_apps_edu_toast_content (8807496014667211562) --> - <skip /> - <!-- no translation found for back_edu_notification_title (5624780717751357278) --> - <skip /> - <!-- no translation found for back_edu_notification_content (2497557451540954068) --> - <skip /> - <!-- no translation found for home_edu_notification_title (6097902076909654045) --> - <skip /> - <!-- no translation found for home_edu_notification_content (6631697734535766588) --> - <skip /> - <!-- no translation found for overview_edu_notification_title (1265824157319562406) --> - <skip /> - <!-- no translation found for overview_edu_notification_content (3578204677648432500) --> - <skip /> - <!-- no translation found for all_apps_edu_notification_title (372262997265569063) --> - <skip /> - <!-- no translation found for all_apps_edu_notification_content (3255070575694025585) --> - <skip /> + <string name="back_edu_toast_content" msgid="4530314597378982956">"Հետ գնալու համար հպահարթակի վրա երեք մատը սահեցրեք ձախ կամ աջ"</string> + <string name="home_edu_toast_content" msgid="3381071147871955415">"Հիմնական էկրան անցնելու համար հպահարթակի վրա երեք մատը սահեցրեք ձախ կամ աջ"</string> + <string name="overview_edu_toast_content" msgid="5797030644017804518">"Վերջերս օգտագործված հավելվածները դիտելու համար երեք մատը սահեցրեք վերև և սեղմած պահեք"</string> + <string name="all_apps_edu_toast_content" msgid="8807496014667211562">"Բոլոր հավելվածները դիտելու համար սեղմեք գործողության ստեղնը ստեղնաշարի վրա"</string> + <string name="back_edu_notification_title" msgid="5624780717751357278">"Օգտագործեք ձեր հպահարթակը՝ վերադառնալու համար"</string> + <string name="back_edu_notification_content" msgid="2497557451540954068">"Երեք մատը սահեցրեք ձախ կամ աջ։ Հպեք՝ ավելի շատ ժեստերի ծանոթանալու համար։"</string> + <string name="home_edu_notification_title" msgid="6097902076909654045">"Օգտագործեք ձեր հպահարթակը՝ հիմնական էկրան անցնելու համար"</string> + <string name="home_edu_notification_content" msgid="6631697734535766588">"Երեք մատը սահեցրեք վերև։ Հպեք՝ ավելի շատ ժեստերի ծանոթանալու համար։"</string> + <string name="overview_edu_notification_title" msgid="1265824157319562406">"Օգտագործեք ձեր հպահարթակը՝ վերջերս օգտագործված հավելվածները դիտելու համար"</string> + <string name="overview_edu_notification_content" msgid="3578204677648432500">"Երեք մատը սահեցրեք վերև և սեղմած պահեք։ Հպեք՝ ավելի շատ ժեստերի ծանոթանալու համար։"</string> + <string name="all_apps_edu_notification_title" msgid="372262997265569063">"Օգտագործեք ձեր ստեղնաշարը՝ բոլոր հավելվածները դիտելու համար"</string> + <string name="all_apps_edu_notification_content" msgid="3255070575694025585">"Ցանկացած ժամանակ սեղմեք գործողության ստեղնը։ Հպեք՝ ավելի շատ ժեստերի ծանոթանալու համար։"</string> </resources> diff --git a/packages/SystemUI/res/values-hy/tiles_states_strings.xml b/packages/SystemUI/res/values-hy/tiles_states_strings.xml index 0f951f65ddb1..eb77ccf8c1fc 100644 --- a/packages/SystemUI/res/values-hy/tiles_states_strings.xml +++ b/packages/SystemUI/res/values-hy/tiles_states_strings.xml @@ -56,11 +56,6 @@ <item msgid="5376619709702103243">"Անջատված է"</item> <item msgid="4875147066469902392">"Միացված է"</item> </string-array> - <string-array name="tile_states_modes"> - <item msgid="7764936419245199023">"Հասանելի չէ"</item> - <item msgid="2004750556637773692">"Անջատված է"</item> - <item msgid="8968530753931637871">"Միացված է"</item> - </string-array> <string-array name="tile_states_flashlight"> <item msgid="3465257127433353857">"Հասանելի չէ"</item> <item msgid="5044688398303285224">"Անջատված է"</item> diff --git a/packages/SystemUI/res/values-in/strings.xml b/packages/SystemUI/res/values-in/strings.xml index 0e30a3cbbec1..873372b1e44c 100644 --- a/packages/SystemUI/res/values-in/strings.xml +++ b/packages/SystemUI/res/values-in/strings.xml @@ -388,6 +388,9 @@ <string name="performance" msgid="6552785217174378320">"Performa"</string> <string name="user_interface" msgid="3712869377953950887">"Antarmuka Pengguna"</string> <string name="thermal" msgid="6758074791325414831">"Termal"</string> + <string name="custom" msgid="3337456985275158299">"Kustom"</string> + <string name="custom_trace_settings_dialog_title" msgid="2608570500144830554">"Setelan Rekaman Aktivitas Kustom"</string> + <string name="restore_default" msgid="5259420807486239755">"Pulihkan Default"</string> <string name="quick_settings_onehanded_label" msgid="2416537930246274991">"Mode satu tangan"</string> <string name="quick_settings_hearing_devices_label" msgid="7277170419679404129">"Alat bantu dengar"</string> <string name="quick_settings_hearing_devices_connected" msgid="6519069502397037781">"Aktif"</string> @@ -429,9 +432,13 @@ <string name="zen_modes_dialog_title" msgid="4159138230418567383">"Mode prioritas"</string> <string name="zen_modes_dialog_done" msgid="6654130880256438950">"Selesai"</string> <string name="zen_modes_dialog_settings" msgid="2310248023728936697">"Setelan"</string> - <!-- no translation found for zen_mode_on (9085304934016242591) --> + <string name="zen_mode_on" msgid="9085304934016242591">"Aktif"</string> + <string name="zen_mode_off" msgid="1736604456618147306">"Nonaktif"</string> + <!-- no translation found for zen_mode_set_up (7457957033034460064) --> <skip /> - <!-- no translation found for zen_mode_off (1736604456618147306) --> + <!-- no translation found for zen_mode_no_manual_invocation (1769975741344633672) --> + <skip /> + <!-- no translation found for zen_mode_active_modes (1625850411578488856) --> <skip /> <string name="zen_priority_introduction" msgid="3159291973383796646">"Anda tidak akan terganggu oleh suara dan getaran, kecuali dari alarm, pengingat, acara, dan penelepon yang Anda tentukan. Anda akan tetap mendengar apa pun yang telah dipilih untuk diputar, termasuk musik, video, dan game."</string> <string name="zen_alarms_introduction" msgid="3987266042682300470">"Anda tidak akan terganggu oleh suara dan getaran, kecuali dari alarm. Anda akan tetap mendengar apa pun yang telah dipilih untuk diputar, termasuk musik, video, dan game."</string> @@ -471,6 +478,8 @@ <string name="keyguard_indication_charging_time_slowly" msgid="301936949731705417">"<xliff:g id="PERCENTAGE">%2$s</xliff:g> • Mengisi daya dengan lambat • Penuh dalam waktu <xliff:g id="CHARGING_TIME_LEFT">%1$s</xliff:g>"</string> <string name="keyguard_indication_charging_time_dock" msgid="3149328898931741271">"<xliff:g id="PERCENTAGE">%2$s</xliff:g> • Mengisi daya • Penuh dalam waktu <xliff:g id="CHARGING_TIME_LEFT">%1$s</xliff:g>"</string> <string name="accessibility_action_open_communal_hub" msgid="3081702792413787849">"Widget di layar kunci"</string> + <!-- no translation found for accessibility_announcement_communal_widget_added (6911593106099328271) --> + <skip /> <string name="communal_tutorial_indicator_text" msgid="4503010353591430123">"Geser ke kiri untuk memulai tutorial komunal"</string> <string name="cta_tile_button_to_open_widget_editor" msgid="3871562362382963878">"Sesuaikan"</string> <string name="cta_tile_button_to_dismiss" msgid="3377597875997861754">"Tutup"</string> @@ -499,8 +508,7 @@ <string name="accessibility_action_label_place_widget" msgid="1914197458644168978">"letakkan widget yang dipilih"</string> <string name="communal_widget_picker_title" msgid="1953369090475731663">"Widget layar kunci"</string> <string name="communal_widget_picker_description" msgid="490515450110487871">"Siapa saja dapat melihat widget di layar kunci Anda, meskipun tablet terkunci."</string> - <!-- no translation found for accessibility_action_label_unselect_widget (1041811747619468698) --> - <skip /> + <string name="accessibility_action_label_unselect_widget" msgid="1041811747619468698">"batalkan pilihan widget"</string> <string name="communal_widgets_disclaimer_title" msgid="1150954395585308868">"Widget layar kunci"</string> <string name="communal_widgets_disclaimer_text" msgid="1423545475160506349">"Untuk membuka aplikasi menggunakan widget, Anda perlu memverifikasi diri Anda. Selain itu, harap ingat bahwa siapa saja dapat melihatnya, bahkan saat tablet Anda terkunci. Beberapa widget mungkin tidak dirancang untuk layar kunci Anda dan mungkin tidak aman untuk ditambahkan di sini."</string> <string name="communal_widgets_disclaimer_button" msgid="4423059765740780753">"Oke"</string> @@ -557,10 +565,8 @@ <string name="media_projection_action_text" msgid="3634906766918186440">"Mulai sekarang"</string> <string name="empty_shade_text" msgid="8935967157319717412">"Tidak ada notifikasi"</string> <string name="no_unseen_notif_text" msgid="395512586119868682">"Tidak ada notifikasi baru"</string> - <!-- no translation found for adaptive_notification_edu_hun_title (7790738150177329960) --> - <skip /> - <!-- no translation found for adaptive_notification_edu_hun_text (7743367744129536610) --> - <skip /> + <string name="adaptive_notification_edu_hun_title" msgid="7790738150177329960">"Pengurangan suara dan getaran notifikasi aktif"</string> + <string name="adaptive_notification_edu_hun_text" msgid="7743367744129536610">"Saat Anda menerima terlalu banyak notifikasi sekaligus, volume dan notifikasi perangkat akan otomatis dikurangi hingga selama 2 menit."</string> <string name="go_to_adaptive_notification_settings" msgid="2423690125178298479">"Nonaktifkan"</string> <string name="unlock_to_see_notif_text" msgid="7439033907167561227">"Buka kunci untuk melihat notifikasi lama"</string> <string name="quick_settings_disclosure_parental_controls" msgid="2114102871438223600">"Perangkat ini dikelola oleh orang tuamu"</string> @@ -1226,7 +1232,6 @@ <string name="accessibility_fingerprint_bouncer" msgid="7189102492498735519">"Perlu autentikasi. Sentuh sensor sidik jari untuk melakukan autentikasi."</string> <string name="ongoing_phone_call_content_description" msgid="5332334388483099947">"Panggilan telepon sedang berlangsung"</string> <string name="mobile_data_settings_title" msgid="3955246641380064901">"Data seluler"</string> - <string name="preference_summary_default_combination" msgid="8453246369903749670">"<xliff:g id="STATE">%1$s</xliff:g>/<xliff:g id="NETWORKMODE">%2$s</xliff:g>"</string> <string name="mobile_data_connection_active" msgid="944490013299018227">"Terhubung"</string> <string name="mobile_data_temp_connection_active" msgid="4590222725908806824">"Terhubung sementara"</string> <string name="mobile_data_poor_connection" msgid="819617772268371434">"Koneksi buruk"</string> @@ -1380,7 +1385,10 @@ <string name="touchpad_tutorial_done_button" msgid="176168488821755503">"Selesai"</string> <string name="touchpad_tutorial_gesture_done" msgid="4784438360736821255">"Bagus!"</string> <string name="touchpad_back_gesture_action_title" msgid="7199067250654332735">"Kembali"</string> - <string name="touchpad_back_gesture_guidance" msgid="4222430588599527272">"Untuk kembali, geser ke kiri atau ke kanan menggunakan tiga jari ke mana saja di touchpad."</string> + <!-- no translation found for touchpad_back_gesture_guidance (6263750214998421587) --> + <skip /> + <!-- no translation found for touchpad_back_gesture_finished (5353616006999726249) --> + <skip /> <string name="touchpad_back_gesture_animation_content_description" msgid="2646107450922379918">"Touchpad menampilkan tiga jari yang bergerak ke kanan dan ke kiri"</string> <string name="touchpad_back_gesture_screen_animation_content_description" msgid="4036267494237748710">"Layar perangkat menampilkan animasi untuk gestur kembali"</string> <string name="keyboard_backlight_dialog_title" msgid="8273102932345564724">"Lampu latar keyboard"</string> @@ -1388,28 +1396,16 @@ <string name="home_controls_dream_label" msgid="6567105701292324257">"Kontrol Rumah"</string> <string name="home_controls_dream_description" msgid="4644150952104035789">"Akses cepat kontrol rumah Anda sebagai screensaver"</string> <string name="volume_undo_action" msgid="5815519725211877114">"Urungkan"</string> - <!-- no translation found for back_edu_toast_content (4530314597378982956) --> - <skip /> - <!-- no translation found for home_edu_toast_content (3381071147871955415) --> - <skip /> - <!-- no translation found for overview_edu_toast_content (5797030644017804518) --> - <skip /> - <!-- no translation found for all_apps_edu_toast_content (8807496014667211562) --> - <skip /> - <!-- no translation found for back_edu_notification_title (5624780717751357278) --> - <skip /> - <!-- no translation found for back_edu_notification_content (2497557451540954068) --> - <skip /> - <!-- no translation found for home_edu_notification_title (6097902076909654045) --> - <skip /> - <!-- no translation found for home_edu_notification_content (6631697734535766588) --> - <skip /> - <!-- no translation found for overview_edu_notification_title (1265824157319562406) --> - <skip /> - <!-- no translation found for overview_edu_notification_content (3578204677648432500) --> - <skip /> - <!-- no translation found for all_apps_edu_notification_title (372262997265569063) --> - <skip /> - <!-- no translation found for all_apps_edu_notification_content (3255070575694025585) --> - <skip /> + <string name="back_edu_toast_content" msgid="4530314597378982956">"Untuk kembali, geser ke kiri atau kanan menggunakan tiga jari di touchpad"</string> + <string name="home_edu_toast_content" msgid="3381071147871955415">"Untuk membuka layar utama, geser ke atas menggunakan tiga jari di touchpad"</string> + <string name="overview_edu_toast_content" msgid="5797030644017804518">"Untuk melihat aplikasi terkini, geser ke atas dan tahan menggunakan tiga jari di touchpad"</string> + <string name="all_apps_edu_toast_content" msgid="8807496014667211562">"Untuk melihat semua aplikasi, tekan tombol tindakan di keyboard"</string> + <string name="back_edu_notification_title" msgid="5624780717751357278">"Gunakan touchpad untuk kembali"</string> + <string name="back_edu_notification_content" msgid="2497557451540954068">"Geser ke kiri atau kanan menggunakan tiga jari. Ketuk untuk mempelajari gestur lainnya."</string> + <string name="home_edu_notification_title" msgid="6097902076909654045">"Gunakan touchpad untuk membuka layar utama"</string> + <string name="home_edu_notification_content" msgid="6631697734535766588">"Geser ke atas menggunakan tiga jari. Ketuk untuk mempelajari gestur lainnya."</string> + <string name="overview_edu_notification_title" msgid="1265824157319562406">"Gunakan touchpad untuk melihat aplikasi terkini"</string> + <string name="overview_edu_notification_content" msgid="3578204677648432500">"Geser ke atas dan tahan menggunakan tiga jari. Ketuk untuk mempelajari gestur lainnya."</string> + <string name="all_apps_edu_notification_title" msgid="372262997265569063">"Gunakan keyboard untuk melihat semua aplikasi"</string> + <string name="all_apps_edu_notification_content" msgid="3255070575694025585">"Tekan tombol tindakan kapan saja. Ketuk untuk mempelajari gestur lainnya."</string> </resources> diff --git a/packages/SystemUI/res/values-in/tiles_states_strings.xml b/packages/SystemUI/res/values-in/tiles_states_strings.xml index f05d99dc89b4..a415f644fb48 100644 --- a/packages/SystemUI/res/values-in/tiles_states_strings.xml +++ b/packages/SystemUI/res/values-in/tiles_states_strings.xml @@ -56,11 +56,6 @@ <item msgid="5376619709702103243">"Nonaktif"</item> <item msgid="4875147066469902392">"Aktif"</item> </string-array> - <string-array name="tile_states_modes"> - <item msgid="7764936419245199023">"Tidak tersedia"</item> - <item msgid="2004750556637773692">"Nonaktif"</item> - <item msgid="8968530753931637871">"Aktif"</item> - </string-array> <string-array name="tile_states_flashlight"> <item msgid="3465257127433353857">"Tidak tersedia"</item> <item msgid="5044688398303285224">"Mati"</item> diff --git a/packages/SystemUI/res/values-is/strings.xml b/packages/SystemUI/res/values-is/strings.xml index 2fc70735cdfd..50145b06a06e 100644 --- a/packages/SystemUI/res/values-is/strings.xml +++ b/packages/SystemUI/res/values-is/strings.xml @@ -388,6 +388,9 @@ <string name="performance" msgid="6552785217174378320">"Afköst"</string> <string name="user_interface" msgid="3712869377953950887">"Notandaviðmót"</string> <string name="thermal" msgid="6758074791325414831">"Varmi"</string> + <string name="custom" msgid="3337456985275158299">"Sérsnið"</string> + <string name="custom_trace_settings_dialog_title" msgid="2608570500144830554">"Sérsniðnar rakningarstillingar"</string> + <string name="restore_default" msgid="5259420807486239755">"Endurheimta sjálfgildi"</string> <string name="quick_settings_onehanded_label" msgid="2416537930246274991">"Einhent stilling"</string> <string name="quick_settings_hearing_devices_label" msgid="7277170419679404129">"Heyrnartæki"</string> <string name="quick_settings_hearing_devices_connected" msgid="6519069502397037781">"Virk"</string> @@ -429,9 +432,13 @@ <string name="zen_modes_dialog_title" msgid="4159138230418567383">"Forgangsstillingar"</string> <string name="zen_modes_dialog_done" msgid="6654130880256438950">"Lokið"</string> <string name="zen_modes_dialog_settings" msgid="2310248023728936697">"Stillingar"</string> - <!-- no translation found for zen_mode_on (9085304934016242591) --> + <string name="zen_mode_on" msgid="9085304934016242591">"Kveikt"</string> + <string name="zen_mode_off" msgid="1736604456618147306">"Slökkt"</string> + <!-- no translation found for zen_mode_set_up (7457957033034460064) --> <skip /> - <!-- no translation found for zen_mode_off (1736604456618147306) --> + <!-- no translation found for zen_mode_no_manual_invocation (1769975741344633672) --> + <skip /> + <!-- no translation found for zen_mode_active_modes (1625850411578488856) --> <skip /> <string name="zen_priority_introduction" msgid="3159291973383796646">"Þú verður ekki fyrir truflunum frá hljóðmerkjum og titringi, fyrir utan vekjara, áminningar, viðburði og símtöl frá þeim sem þú leyfir fyrirfram. Þú heyrir áfram í öllu sem þú velur að spila, svo sem tónlist, myndskeiðum og leikjum."</string> <string name="zen_alarms_introduction" msgid="3987266042682300470">"Þú verður ekki fyrir truflunum frá hljóðmerkjum og titringi, fyrir utan vekjara. Þú heyrir áfram í öllu sem þú velur að spila, svo sem tónlist, myndskeiðum og leikjum."</string> @@ -471,6 +478,8 @@ <string name="keyguard_indication_charging_time_slowly" msgid="301936949731705417">"<xliff:g id="PERCENTAGE">%2$s</xliff:g> • Hæg hleðsla • Full hleðsla eftir <xliff:g id="CHARGING_TIME_LEFT">%1$s</xliff:g>"</string> <string name="keyguard_indication_charging_time_dock" msgid="3149328898931741271">"<xliff:g id="PERCENTAGE">%2$s</xliff:g> • Í hleðslu • Full hleðsla eftir <xliff:g id="CHARGING_TIME_LEFT">%1$s</xliff:g>"</string> <string name="accessibility_action_open_communal_hub" msgid="3081702792413787849">"Græjur á lásskjá"</string> + <!-- no translation found for accessibility_announcement_communal_widget_added (6911593106099328271) --> + <skip /> <string name="communal_tutorial_indicator_text" msgid="4503010353591430123">"Strjúktu til vinstri til að hefja samfélagsleiðsögnina"</string> <string name="cta_tile_button_to_open_widget_editor" msgid="3871562362382963878">"Sérsníða"</string> <string name="cta_tile_button_to_dismiss" msgid="3377597875997861754">"Hunsa"</string> @@ -499,8 +508,7 @@ <string name="accessibility_action_label_place_widget" msgid="1914197458644168978">"koma valinni græju fyrir"</string> <string name="communal_widget_picker_title" msgid="1953369090475731663">"Græjur á lásskjá"</string> <string name="communal_widget_picker_description" msgid="490515450110487871">"Hver sem er getur séð græjur á lásskjánum þínum, jafnvel þótt spjaldtölvan sé læst."</string> - <!-- no translation found for accessibility_action_label_unselect_widget (1041811747619468698) --> - <skip /> + <string name="accessibility_action_label_unselect_widget" msgid="1041811747619468698">"afturkalla val á græju"</string> <string name="communal_widgets_disclaimer_title" msgid="1150954395585308868">"Græjur fyrir lásskjá"</string> <string name="communal_widgets_disclaimer_text" msgid="1423545475160506349">"Þú þarft að staðfesta að þetta sért þú til að geta opnað forrit með græju. Hafðu einnig í huga að hver sem er getur skoðað þær, jafnvel þótt spjaldtölvan sé læst. Sumar græjur eru hugsanlega ekki ætlaðar fyrir lásskjá og því gæti verið óöruggt að bæta þeim við hér."</string> <string name="communal_widgets_disclaimer_button" msgid="4423059765740780753">"Ég skil"</string> @@ -557,10 +565,8 @@ <string name="media_projection_action_text" msgid="3634906766918186440">"Byrja núna"</string> <string name="empty_shade_text" msgid="8935967157319717412">"Engar tilkynningar"</string> <string name="no_unseen_notif_text" msgid="395512586119868682">"Engar nýjar tilkynningar"</string> - <!-- no translation found for adaptive_notification_edu_hun_title (7790738150177329960) --> - <skip /> - <!-- no translation found for adaptive_notification_edu_hun_text (7743367744129536610) --> - <skip /> + <string name="adaptive_notification_edu_hun_title" msgid="7790738150177329960">"Kveikt er á tilkynningadempun"</string> + <string name="adaptive_notification_edu_hun_text" msgid="7743367744129536610">"Lækkað er sjálfkrafa í hljóðstyrk og áminningum tækisins í allt að tvær mínútur þegar þú færð of margar tilkynningar í einu."</string> <string name="go_to_adaptive_notification_settings" msgid="2423690125178298479">"Slökkva"</string> <string name="unlock_to_see_notif_text" msgid="7439033907167561227">"Taktu úr lás til að sjá eldri tilkynningar"</string> <string name="quick_settings_disclosure_parental_controls" msgid="2114102871438223600">"Foreldri þitt stjórnar þessu tæki"</string> @@ -1226,7 +1232,6 @@ <string name="accessibility_fingerprint_bouncer" msgid="7189102492498735519">"Auðkenningar krafist. Auðkenndu með því að snerta fingrafaralesarann."</string> <string name="ongoing_phone_call_content_description" msgid="5332334388483099947">"Símtal í gangi"</string> <string name="mobile_data_settings_title" msgid="3955246641380064901">"Farsímagögn"</string> - <string name="preference_summary_default_combination" msgid="8453246369903749670">"<xliff:g id="STATE">%1$s</xliff:g> / <xliff:g id="NETWORKMODE">%2$s</xliff:g>"</string> <string name="mobile_data_connection_active" msgid="944490013299018227">"Tengt"</string> <string name="mobile_data_temp_connection_active" msgid="4590222725908806824">"Tímabundin tenging"</string> <string name="mobile_data_poor_connection" msgid="819617772268371434">"Léleg tenging"</string> @@ -1380,7 +1385,10 @@ <string name="touchpad_tutorial_done_button" msgid="176168488821755503">"Lokið"</string> <string name="touchpad_tutorial_gesture_done" msgid="4784438360736821255">"Vel gert!"</string> <string name="touchpad_back_gesture_action_title" msgid="7199067250654332735">"Til baka"</string> - <string name="touchpad_back_gesture_guidance" msgid="4222430588599527272">"Strjúktu til vinstri eða hægri með þrem fingrum hvar sem er á snertifletinum til að fara til baka."</string> + <!-- no translation found for touchpad_back_gesture_guidance (6263750214998421587) --> + <skip /> + <!-- no translation found for touchpad_back_gesture_finished (5353616006999726249) --> + <skip /> <string name="touchpad_back_gesture_animation_content_description" msgid="2646107450922379918">"Snertiflötur sem sýnir þrjá fingur færast til hægri og vinstri"</string> <string name="touchpad_back_gesture_screen_animation_content_description" msgid="4036267494237748710">"Skjár tækis sem sýnir hreyfimynd fyrir bendinguna „til baka“."</string> <string name="keyboard_backlight_dialog_title" msgid="8273102932345564724">"Baklýsing lyklaborðs"</string> @@ -1388,28 +1396,16 @@ <string name="home_controls_dream_label" msgid="6567105701292324257">"Heimastýringar"</string> <string name="home_controls_dream_description" msgid="4644150952104035789">"Fáðu skjótan aðgang að heimastýringum sem skjávara"</string> <string name="volume_undo_action" msgid="5815519725211877114">"Afturkalla"</string> - <!-- no translation found for back_edu_toast_content (4530314597378982956) --> - <skip /> - <!-- no translation found for home_edu_toast_content (3381071147871955415) --> - <skip /> - <!-- no translation found for overview_edu_toast_content (5797030644017804518) --> - <skip /> - <!-- no translation found for all_apps_edu_toast_content (8807496014667211562) --> - <skip /> - <!-- no translation found for back_edu_notification_title (5624780717751357278) --> - <skip /> - <!-- no translation found for back_edu_notification_content (2497557451540954068) --> - <skip /> - <!-- no translation found for home_edu_notification_title (6097902076909654045) --> - <skip /> - <!-- no translation found for home_edu_notification_content (6631697734535766588) --> - <skip /> - <!-- no translation found for overview_edu_notification_title (1265824157319562406) --> - <skip /> - <!-- no translation found for overview_edu_notification_content (3578204677648432500) --> - <skip /> - <!-- no translation found for all_apps_edu_notification_title (372262997265569063) --> - <skip /> - <!-- no translation found for all_apps_edu_notification_content (3255070575694025585) --> - <skip /> + <string name="back_edu_toast_content" msgid="4530314597378982956">"Strjúktu til vinstri eða hægri með þremur fingrum á snertifletinum til að fara til baka"</string> + <string name="home_edu_toast_content" msgid="3381071147871955415">"Strjúktu upp með þremur fingrum á snertifletinum til að fara á heimaskjá"</string> + <string name="overview_edu_toast_content" msgid="5797030644017804518">"Strjúktu upp og haltu með þremur fingrum á snertifletinum til að sjá nýleg forrit"</string> + <string name="all_apps_edu_toast_content" msgid="8807496014667211562">"Ýttu á aðgerðalykilinn á lyklaborðinu til að sjá öll forritin þín"</string> + <string name="back_edu_notification_title" msgid="5624780717751357278">"Notaðu snertiflötinn til að fara til baka"</string> + <string name="back_edu_notification_content" msgid="2497557451540954068">"Strjúktu til vinstri eða hægri með þremur fingrum. Ýttu til að læra fleiri bendingar."</string> + <string name="home_edu_notification_title" msgid="6097902076909654045">"Notaðu snertiflötinn til að fara á heimaskjá"</string> + <string name="home_edu_notification_content" msgid="6631697734535766588">"Strjúktu upp með þremur fingrum. Ýttu til að læra fleiri bendingar."</string> + <string name="overview_edu_notification_title" msgid="1265824157319562406">"Notaðu snertiflötinn til að sjá nýleg forrit"</string> + <string name="overview_edu_notification_content" msgid="3578204677648432500">"Strjúktu upp og haltu með þremur fingrum. Ýttu til að læra fleiri bendingar."</string> + <string name="all_apps_edu_notification_title" msgid="372262997265569063">"Notaðu lyklaborðið til að sjá öll forrit"</string> + <string name="all_apps_edu_notification_content" msgid="3255070575694025585">"Ýttu hvenær sem er á aðgerðalykilinn. Ýttu til að læra fleiri bendingar."</string> </resources> diff --git a/packages/SystemUI/res/values-is/tiles_states_strings.xml b/packages/SystemUI/res/values-is/tiles_states_strings.xml index d13075e78fa0..c9befd6574c4 100644 --- a/packages/SystemUI/res/values-is/tiles_states_strings.xml +++ b/packages/SystemUI/res/values-is/tiles_states_strings.xml @@ -56,11 +56,6 @@ <item msgid="5376619709702103243">"Slökkt"</item> <item msgid="4875147066469902392">"Kveikt"</item> </string-array> - <string-array name="tile_states_modes"> - <item msgid="7764936419245199023">"Ekki tiltækt"</item> - <item msgid="2004750556637773692">"Slökkt"</item> - <item msgid="8968530753931637871">"Kveikt"</item> - </string-array> <string-array name="tile_states_flashlight"> <item msgid="3465257127433353857">"Ekki í boði"</item> <item msgid="5044688398303285224">"Slökkt"</item> diff --git a/packages/SystemUI/res/values-it/strings.xml b/packages/SystemUI/res/values-it/strings.xml index d36d8ccfa14f..502678eb3e47 100644 --- a/packages/SystemUI/res/values-it/strings.xml +++ b/packages/SystemUI/res/values-it/strings.xml @@ -390,6 +390,9 @@ <string name="performance" msgid="6552785217174378320">"Prestazioni"</string> <string name="user_interface" msgid="3712869377953950887">"Interfaccia utente"</string> <string name="thermal" msgid="6758074791325414831">"Termico"</string> + <string name="custom" msgid="3337456985275158299">"Personalizzate"</string> + <string name="custom_trace_settings_dialog_title" msgid="2608570500144830554">"Impostazioni monitoraggio personalizzate"</string> + <string name="restore_default" msgid="5259420807486239755">"Ripristina predefinite"</string> <string name="quick_settings_onehanded_label" msgid="2416537930246274991">"Modalità a una mano"</string> <string name="quick_settings_hearing_devices_label" msgid="7277170419679404129">"Apparecchi acustici"</string> <string name="quick_settings_hearing_devices_connected" msgid="6519069502397037781">"Attivi"</string> @@ -431,10 +434,11 @@ <string name="zen_modes_dialog_title" msgid="4159138230418567383">"Modalità priorità"</string> <string name="zen_modes_dialog_done" msgid="6654130880256438950">"Fine"</string> <string name="zen_modes_dialog_settings" msgid="2310248023728936697">"Impostazioni"</string> - <!-- no translation found for zen_mode_on (9085304934016242591) --> - <skip /> - <!-- no translation found for zen_mode_off (1736604456618147306) --> - <skip /> + <string name="zen_mode_on" msgid="9085304934016242591">"On"</string> + <string name="zen_mode_off" msgid="1736604456618147306">"Off"</string> + <string name="zen_mode_set_up" msgid="7457957033034460064">"Configura"</string> + <string name="zen_mode_no_manual_invocation" msgid="1769975741344633672">"Gestisci nelle impostazioni"</string> + <string name="zen_mode_active_modes" msgid="1625850411578488856">"{count,plural, =0{Nessuna modalità attiva}=1{{mode} è attiva}many{# di modalità sono attive}other{# modalità sono attive}}"</string> <string name="zen_priority_introduction" msgid="3159291973383796646">"Suoni e vibrazioni non ti disturberanno, ad eccezione di sveglie, promemoria, eventi, chiamate da contatti da te specificati ed elementi che hai scelto di continuare a riprodurre, inclusi video, musica e giochi."</string> <string name="zen_alarms_introduction" msgid="3987266042682300470">"Non riceverai distrazioni da suoni e vibrazioni, ad eccezione delle sveglie. Potrai comunque sentire qualunque cosa decidi di riprodurre, inclusi video, musica e giochi."</string> <string name="zen_priority_customize_button" msgid="4119213187257195047">"Personalizza"</string> @@ -473,6 +477,8 @@ <string name="keyguard_indication_charging_time_slowly" msgid="301936949731705417">"<xliff:g id="PERCENTAGE">%2$s</xliff:g> • Ricarica lenta • <xliff:g id="CHARGING_TIME_LEFT">%1$s</xliff:g> alla ricarica completa"</string> <string name="keyguard_indication_charging_time_dock" msgid="3149328898931741271">"<xliff:g id="PERCENTAGE">%2$s</xliff:g> • In carica • <xliff:g id="CHARGING_TIME_LEFT">%1$s</xliff:g> alla ricarica completa"</string> <string name="accessibility_action_open_communal_hub" msgid="3081702792413787849">"Widget su schermata di blocco"</string> + <!-- no translation found for accessibility_announcement_communal_widget_added (6911593106099328271) --> + <skip /> <string name="communal_tutorial_indicator_text" msgid="4503010353591430123">"Scorri a sinistra per iniziare il tutorial della community"</string> <string name="cta_tile_button_to_open_widget_editor" msgid="3871562362382963878">"Personalizza"</string> <string name="cta_tile_button_to_dismiss" msgid="3377597875997861754">"Chiudi"</string> @@ -501,8 +507,7 @@ <string name="accessibility_action_label_place_widget" msgid="1914197458644168978">"posiziona il widget selezionato"</string> <string name="communal_widget_picker_title" msgid="1953369090475731663">"Widget della schermata di blocco"</string> <string name="communal_widget_picker_description" msgid="490515450110487871">"Chiunque può visualizzare i widget sulla tua schermata di blocco, anche se il tablet è bloccato."</string> - <!-- no translation found for accessibility_action_label_unselect_widget (1041811747619468698) --> - <skip /> + <string name="accessibility_action_label_unselect_widget" msgid="1041811747619468698">"deseleziona widget"</string> <string name="communal_widgets_disclaimer_title" msgid="1150954395585308868">"Widget della schermata di blocco"</string> <string name="communal_widgets_disclaimer_text" msgid="1423545475160506349">"Per aprire un\'app utilizzando un widget, dovrai verificare la tua identità. Inoltre tieni presente che chiunque può vederlo, anche quando il tablet è bloccato. Alcuni widget potrebbero non essere stati progettati per la schermata di blocco e potrebbe non essere sicuro aggiungerli qui."</string> <string name="communal_widgets_disclaimer_button" msgid="4423059765740780753">"Ok"</string> @@ -559,10 +564,8 @@ <string name="media_projection_action_text" msgid="3634906766918186440">"Avvia adesso"</string> <string name="empty_shade_text" msgid="8935967157319717412">"Nessuna notifica"</string> <string name="no_unseen_notif_text" msgid="395512586119868682">"Nessuna nuova notifica"</string> - <!-- no translation found for adaptive_notification_edu_hun_title (7790738150177329960) --> - <skip /> - <!-- no translation found for adaptive_notification_edu_hun_text (7743367744129536610) --> - <skip /> + <string name="adaptive_notification_edu_hun_title" msgid="7790738150177329960">"Attenuazione delle notifiche attivata"</string> + <string name="adaptive_notification_edu_hun_text" msgid="7743367744129536610">"Volume e avvisi sono ridotti automaticamente fino a 2 minuti quando ricevi troppe notifiche insieme."</string> <string name="go_to_adaptive_notification_settings" msgid="2423690125178298479">"Disattiva"</string> <string name="unlock_to_see_notif_text" msgid="7439033907167561227">"Sblocca per vedere le notifiche meno recenti"</string> <string name="quick_settings_disclosure_parental_controls" msgid="2114102871438223600">"Questo dispositivo è gestito dai tuoi genitori"</string> @@ -1228,7 +1231,6 @@ <string name="accessibility_fingerprint_bouncer" msgid="7189102492498735519">"Autenticazione obbligatoria. Eseguila toccando il sensore di impronte digitali."</string> <string name="ongoing_phone_call_content_description" msgid="5332334388483099947">"Telefonata in corso"</string> <string name="mobile_data_settings_title" msgid="3955246641380064901">"Dati mobili"</string> - <string name="preference_summary_default_combination" msgid="8453246369903749670">"<xliff:g id="STATE">%1$s</xliff:g>/<xliff:g id="NETWORKMODE">%2$s</xliff:g>"</string> <string name="mobile_data_connection_active" msgid="944490013299018227">"Connessa"</string> <string name="mobile_data_temp_connection_active" msgid="4590222725908806824">"Connessa temporaneamente"</string> <string name="mobile_data_poor_connection" msgid="819617772268371434">"Connessione debole"</string> @@ -1382,7 +1384,10 @@ <string name="touchpad_tutorial_done_button" msgid="176168488821755503">"Fine"</string> <string name="touchpad_tutorial_gesture_done" msgid="4784438360736821255">"Ottimo lavoro"</string> <string name="touchpad_back_gesture_action_title" msgid="7199067250654332735">"Indietro"</string> - <string name="touchpad_back_gesture_guidance" msgid="4222430588599527272">"Per tornare indietro, scorri verso sinistra o verso destra utilizzando tre dita in un punto qualsiasi del touchpad."</string> + <!-- no translation found for touchpad_back_gesture_guidance (6263750214998421587) --> + <skip /> + <!-- no translation found for touchpad_back_gesture_finished (5353616006999726249) --> + <skip /> <string name="touchpad_back_gesture_animation_content_description" msgid="2646107450922379918">"Touchpad che mostra tre dita che si muovono verso destra e sinistra"</string> <string name="touchpad_back_gesture_screen_animation_content_description" msgid="4036267494237748710">"Schermata del dispositivo che mostra l\'animazione del gesto per tornare indietro"</string> <string name="keyboard_backlight_dialog_title" msgid="8273102932345564724">"Retroilluminazione della tastiera"</string> @@ -1390,28 +1395,16 @@ <string name="home_controls_dream_label" msgid="6567105701292324257">"Controlli della casa"</string> <string name="home_controls_dream_description" msgid="4644150952104035789">"Accedi rapidamente ai controlli della casa dal salvaschermo"</string> <string name="volume_undo_action" msgid="5815519725211877114">"Annulla"</string> - <!-- no translation found for back_edu_toast_content (4530314597378982956) --> - <skip /> - <!-- no translation found for home_edu_toast_content (3381071147871955415) --> - <skip /> - <!-- no translation found for overview_edu_toast_content (5797030644017804518) --> - <skip /> - <!-- no translation found for all_apps_edu_toast_content (8807496014667211562) --> - <skip /> - <!-- no translation found for back_edu_notification_title (5624780717751357278) --> - <skip /> - <!-- no translation found for back_edu_notification_content (2497557451540954068) --> - <skip /> - <!-- no translation found for home_edu_notification_title (6097902076909654045) --> - <skip /> - <!-- no translation found for home_edu_notification_content (6631697734535766588) --> - <skip /> - <!-- no translation found for overview_edu_notification_title (1265824157319562406) --> - <skip /> - <!-- no translation found for overview_edu_notification_content (3578204677648432500) --> - <skip /> - <!-- no translation found for all_apps_edu_notification_title (372262997265569063) --> - <skip /> - <!-- no translation found for all_apps_edu_notification_content (3255070575694025585) --> - <skip /> + <string name="back_edu_toast_content" msgid="4530314597378982956">"Per tornare indietro, scorri verso sinistra o verso destra con tre dita sul touchpad."</string> + <string name="home_edu_toast_content" msgid="3381071147871955415">"Per andare alla schermata Home, scorri verso l\'alto con tre dita sul touchpad"</string> + <string name="overview_edu_toast_content" msgid="5797030644017804518">"Per visualizzare le app recenti, scorri verso l\'alto e tieni premuto con tre dita sul touchpad"</string> + <string name="all_apps_edu_toast_content" msgid="8807496014667211562">"Per visualizzare tutte le tue app, premi il tasto azione sulla tastiera"</string> + <string name="back_edu_notification_title" msgid="5624780717751357278">"Usa il touchpad per tornare indietro"</string> + <string name="back_edu_notification_content" msgid="2497557451540954068">"Scorri verso sinistra o destra con tre dita. Tocca per scoprire altri gesti."</string> + <string name="home_edu_notification_title" msgid="6097902076909654045">"Usa il touchpad per andare alla schermata Home"</string> + <string name="home_edu_notification_content" msgid="6631697734535766588">"Scorri verso l\'altro con tre dita. Tocca per scoprire altri gesti."</string> + <string name="overview_edu_notification_title" msgid="1265824157319562406">"Usa il touchpad per visualizzare le app recenti"</string> + <string name="overview_edu_notification_content" msgid="3578204677648432500">"Scorri verso l\'alto e tieni premuto con tre dita. Tocca per scoprire altri gesti."</string> + <string name="all_apps_edu_notification_title" msgid="372262997265569063">"Usa la tastiera per visualizzare tutte le app"</string> + <string name="all_apps_edu_notification_content" msgid="3255070575694025585">"Premi il tasto azione in qualsiasi momento. Tocca per scoprire altri gesti."</string> </resources> diff --git a/packages/SystemUI/res/values-it/tiles_states_strings.xml b/packages/SystemUI/res/values-it/tiles_states_strings.xml index 95c33c4acbf4..2fd4f6d49aef 100644 --- a/packages/SystemUI/res/values-it/tiles_states_strings.xml +++ b/packages/SystemUI/res/values-it/tiles_states_strings.xml @@ -56,11 +56,6 @@ <item msgid="5376619709702103243">"Off"</item> <item msgid="4875147066469902392">"On"</item> </string-array> - <string-array name="tile_states_modes"> - <item msgid="7764936419245199023">"Non disponibile"</item> - <item msgid="2004750556637773692">"Off"</item> - <item msgid="8968530753931637871">"On"</item> - </string-array> <string-array name="tile_states_flashlight"> <item msgid="3465257127433353857">"Non disponibile"</item> <item msgid="5044688398303285224">"Off"</item> diff --git a/packages/SystemUI/res/values-iw/strings.xml b/packages/SystemUI/res/values-iw/strings.xml index 553b23d7485b..698d2add6044 100644 --- a/packages/SystemUI/res/values-iw/strings.xml +++ b/packages/SystemUI/res/values-iw/strings.xml @@ -138,13 +138,13 @@ <string name="share_to_app_stop_dialog_message_single_app_generic" msgid="6681016774654578261">"מתבצע כרגע שיתוף של אפליקציה"</string> <string name="share_to_app_stop_dialog_button" msgid="6334056916284230217">"הפסקת השיתוף"</string> <string name="cast_screen_to_other_device_chip_accessibility_label" msgid="4687917476203009885">"הפעלת Cast של המסך מתבצעת"</string> - <string name="cast_to_other_device_stop_dialog_title" msgid="7836517190930357326">"להפסיק את הפעלת ה-Cast?"</string> - <string name="cast_to_other_device_stop_dialog_message_entire_screen_with_device" msgid="1474703115926205251">"מתבצעת כרגע הפעלת Cast של כל המסך שלך למכשיר <xliff:g id="DEVICE_NAME">%1$s</xliff:g>"</string> - <string name="cast_to_other_device_stop_dialog_message_entire_screen" msgid="8419219169553867625">"מתבצעת כרגע הפעלת Cast של כל המסך שלך למכשיר בקרבת מקום"</string> - <string name="cast_to_other_device_stop_dialog_message_specific_app_with_device" msgid="2715934698604085519">"מתבצעת כרגע הפעלת Cast של <xliff:g id="APP_BEING_SHARED_NAME">%1$s</xliff:g> למכשיר <xliff:g id="DEVICE_NAME">%2$s</xliff:g>"</string> - <string name="cast_to_other_device_stop_dialog_message_specific_app" msgid="8616103075630934513">"מתבצעת כרגע הפעלת Cast של <xliff:g id="APP_BEING_SHARED_NAME">%1$s</xliff:g> למכשיר בקרבת מקום"</string> - <string name="cast_to_other_device_stop_dialog_message_generic_with_device" msgid="9213582497852420203">"מתבצעת כרגע הפעלת Cast למכשיר <xliff:g id="DEVICE_NAME">%1$s</xliff:g>"</string> - <string name="cast_to_other_device_stop_dialog_message_generic" msgid="4100272100480415076">"מתבצעת כרגע הפעלת Cast למכשיר בקרבת מקום"</string> + <string name="cast_to_other_device_stop_dialog_title" msgid="7836517190930357326">"להפסיק את פעולת ה-Cast?"</string> + <string name="cast_to_other_device_stop_dialog_message_entire_screen_with_device" msgid="1474703115926205251">"מתבצעת כרגע פעולת Cast של כל המסך שלך למכשיר <xliff:g id="DEVICE_NAME">%1$s</xliff:g>"</string> + <string name="cast_to_other_device_stop_dialog_message_entire_screen" msgid="8419219169553867625">"מתבצעת כרגע פעולת Cast של כל המסך שלך למכשיר בקרבת מקום"</string> + <string name="cast_to_other_device_stop_dialog_message_specific_app_with_device" msgid="2715934698604085519">"מתבצעת כרגע פעולת Cast של <xliff:g id="APP_BEING_SHARED_NAME">%1$s</xliff:g> למכשיר <xliff:g id="DEVICE_NAME">%2$s</xliff:g>"</string> + <string name="cast_to_other_device_stop_dialog_message_specific_app" msgid="8616103075630934513">"מתבצעת כרגע פעולת Cast של <xliff:g id="APP_BEING_SHARED_NAME">%1$s</xliff:g> למכשיר בקרבת מקום"</string> + <string name="cast_to_other_device_stop_dialog_message_generic_with_device" msgid="9213582497852420203">"מתבצעת כרגע פעולת Cast למכשיר <xliff:g id="DEVICE_NAME">%1$s</xliff:g>"</string> + <string name="cast_to_other_device_stop_dialog_message_generic" msgid="4100272100480415076">"מתבצעת כרגע פעולת Cast למכשיר בקרבת מקום"</string> <string name="cast_to_other_device_stop_dialog_button" msgid="6420183747435521834">"הפסקת ה-Cast"</string> <string name="close_dialog_button" msgid="4749497706540104133">"סגירה"</string> <string name="issuerecord_title" msgid="286627115110121849">"בעיה במכשיר ההקלטה"</string> @@ -388,6 +388,9 @@ <string name="performance" msgid="6552785217174378320">"ביצועים"</string> <string name="user_interface" msgid="3712869377953950887">"ממשק משתמש"</string> <string name="thermal" msgid="6758074791325414831">"תרמי"</string> + <string name="custom" msgid="3337456985275158299">"בהתאמה אישית"</string> + <string name="custom_trace_settings_dialog_title" msgid="2608570500144830554">"הגדרות מעקב מותאמות אישית"</string> + <string name="restore_default" msgid="5259420807486239755">"שחזור של ברירת המחדל"</string> <string name="quick_settings_onehanded_label" msgid="2416537930246274991">"מצב שימוש ביד אחת"</string> <string name="quick_settings_hearing_devices_label" msgid="7277170419679404129">"מכשירי שמיעה"</string> <string name="quick_settings_hearing_devices_connected" msgid="6519069502397037781">"פעיל"</string> @@ -429,9 +432,13 @@ <string name="zen_modes_dialog_title" msgid="4159138230418567383">"מצבי עדיפות"</string> <string name="zen_modes_dialog_done" msgid="6654130880256438950">"סיום"</string> <string name="zen_modes_dialog_settings" msgid="2310248023728936697">"הגדרות"</string> - <!-- no translation found for zen_mode_on (9085304934016242591) --> + <string name="zen_mode_on" msgid="9085304934016242591">"מצב מופעל"</string> + <string name="zen_mode_off" msgid="1736604456618147306">"מצב מושבת"</string> + <!-- no translation found for zen_mode_set_up (7457957033034460064) --> <skip /> - <!-- no translation found for zen_mode_off (1736604456618147306) --> + <!-- no translation found for zen_mode_no_manual_invocation (1769975741344633672) --> + <skip /> + <!-- no translation found for zen_mode_active_modes (1625850411578488856) --> <skip /> <string name="zen_priority_introduction" msgid="3159291973383796646">"כדי לא להפריע לך, המכשיר לא ירטוט ולא ישמיע שום צליל, חוץ מהתראות, תזכורות, אירועים ושיחות ממתקשרים מסוימים לבחירתך. המצב הזה לא ישפיע על צלילים שהם חלק מתוכן שבחרת להפעיל, כמו מוזיקה, סרטונים ומשחקים."</string> <string name="zen_alarms_introduction" msgid="3987266042682300470">"כדי לא להפריע לך, המכשיר לא ירטוט ולא ישמיע שום צליל, חוץ מהתראות. המצב הזה לא ישפיע על צלילים שהם חלק מתוכן שבחרת להפעיל, כמו מוזיקה, סרטונים ומשחקים."</string> @@ -471,6 +478,8 @@ <string name="keyguard_indication_charging_time_slowly" msgid="301936949731705417">"<xliff:g id="PERCENTAGE">%2$s</xliff:g> • בטעינה איטית • <xliff:g id="CHARGING_TIME_LEFT">%1$s</xliff:g> עד לסיום"</string> <string name="keyguard_indication_charging_time_dock" msgid="3149328898931741271">"<xliff:g id="PERCENTAGE">%2$s</xliff:g> • בטעינה • <xliff:g id="CHARGING_TIME_LEFT">%1$s</xliff:g> עד לסיום"</string> <string name="accessibility_action_open_communal_hub" msgid="3081702792413787849">"ווידג\'טים במסך הנעילה"</string> + <!-- no translation found for accessibility_announcement_communal_widget_added (6911593106099328271) --> + <skip /> <string name="communal_tutorial_indicator_text" msgid="4503010353591430123">"אפשר להחליק שמאלה כדי להפעיל את המדריך המשותף"</string> <string name="cta_tile_button_to_open_widget_editor" msgid="3871562362382963878">"התאמה אישית"</string> <string name="cta_tile_button_to_dismiss" msgid="3377597875997861754">"סגירה"</string> @@ -499,8 +508,7 @@ <string name="accessibility_action_label_place_widget" msgid="1914197458644168978">"צריך למקם את הווידג\'ט שנבחר"</string> <string name="communal_widget_picker_title" msgid="1953369090475731663">"ווידג\'טים במסך הנעילה"</string> <string name="communal_widget_picker_description" msgid="490515450110487871">"כולם יכולים לראות את הווידג\'טים במסך הנעילה שלך, גם אם הטאבלט נעול."</string> - <!-- no translation found for accessibility_action_label_unselect_widget (1041811747619468698) --> - <skip /> + <string name="accessibility_action_label_unselect_widget" msgid="1041811747619468698">"ביטול הבחירה בווידג\'ט"</string> <string name="communal_widgets_disclaimer_title" msgid="1150954395585308868">"ווידג\'טים במסך הנעילה"</string> <string name="communal_widgets_disclaimer_text" msgid="1423545475160506349">"כדי לפתוח אפליקציה באמצעות ווידג\'ט, עליך לאמת את זהותך. בנוסף, כדאי לזכור שכל אחד יכול לראות את הווידג\'טים גם כשהטאבלט שלך נעול. יכול להיות שחלק מהווידג\'טים לא נועדו למסך הנעילה ושלא בטוח להוסיף אותם לכאן."</string> <string name="communal_widgets_disclaimer_button" msgid="4423059765740780753">"הבנתי"</string> @@ -557,10 +565,8 @@ <string name="media_projection_action_text" msgid="3634906766918186440">"כן, אפשר להתחיל"</string> <string name="empty_shade_text" msgid="8935967157319717412">"אין התראות"</string> <string name="no_unseen_notif_text" msgid="395512586119868682">"אין התראות חדשות"</string> - <!-- no translation found for adaptive_notification_edu_hun_title (7790738150177329960) --> - <skip /> - <!-- no translation found for adaptive_notification_edu_hun_text (7743367744129536610) --> - <skip /> + <string name="adaptive_notification_edu_hun_title" msgid="7790738150177329960">"הפוגת ההתראות מופעלת"</string> + <string name="adaptive_notification_edu_hun_text" msgid="7743367744129536610">"עוצמת הקול וההתראות במכשיר מופחתות אוטומטית למשך עד 2 דקות כשמתקבלות יותר מדי התראות בבת אחת."</string> <string name="go_to_adaptive_notification_settings" msgid="2423690125178298479">"השבתה"</string> <string name="unlock_to_see_notif_text" msgid="7439033907167561227">"יש לבטל את הנעילה כדי לראות התראות ישנות"</string> <string name="quick_settings_disclosure_parental_controls" msgid="2114102871438223600">"המכשיר הזה מנוהל על ידי ההורה שלך"</string> @@ -1226,7 +1232,6 @@ <string name="accessibility_fingerprint_bouncer" msgid="7189102492498735519">"נדרש אימות. יש לגעת בחיישן טביעות האצבע כדי לבצע אימות."</string> <string name="ongoing_phone_call_content_description" msgid="5332334388483099947">"מתקיימת שיחה"</string> <string name="mobile_data_settings_title" msgid="3955246641380064901">"חבילת גלישה"</string> - <string name="preference_summary_default_combination" msgid="8453246369903749670">"<xliff:g id="STATE">%1$s</xliff:g> / <xliff:g id="NETWORKMODE">%2$s</xliff:g>"</string> <string name="mobile_data_connection_active" msgid="944490013299018227">"מחובר"</string> <string name="mobile_data_temp_connection_active" msgid="4590222725908806824">"מחובר באופן זמני"</string> <string name="mobile_data_poor_connection" msgid="819617772268371434">"חיבור באיכות ירודה"</string> @@ -1380,7 +1385,10 @@ <string name="touchpad_tutorial_done_button" msgid="176168488821755503">"סיום"</string> <string name="touchpad_tutorial_gesture_done" msgid="4784438360736821255">"מעולה!"</string> <string name="touchpad_back_gesture_action_title" msgid="7199067250654332735">"חזרה"</string> - <string name="touchpad_back_gesture_guidance" msgid="4222430588599527272">"כדי לחזור אחורה, מחליקים שמאלה או ימינה עם שלוש אצבעות בכל מקום על לוח המגע."</string> + <!-- no translation found for touchpad_back_gesture_guidance (6263750214998421587) --> + <skip /> + <!-- no translation found for touchpad_back_gesture_finished (5353616006999726249) --> + <skip /> <string name="touchpad_back_gesture_animation_content_description" msgid="2646107450922379918">"לוח מגע שמראה שלוש אצבעות זזות ימינה ושמאלה"</string> <string name="touchpad_back_gesture_screen_animation_content_description" msgid="4036267494237748710">"מסך מכשיר שמראה אנימציה לתנועה אחורה"</string> <string name="keyboard_backlight_dialog_title" msgid="8273102932345564724">"התאורה האחורית במקלדת"</string> @@ -1388,28 +1396,16 @@ <string name="home_controls_dream_label" msgid="6567105701292324257">"שליטה במכשירים"</string> <string name="home_controls_dream_description" msgid="4644150952104035789">"גישה מהירה לממשק השליטה במכשירים כשומר מסך"</string> <string name="volume_undo_action" msgid="5815519725211877114">"ביטול"</string> - <!-- no translation found for back_edu_toast_content (4530314597378982956) --> - <skip /> - <!-- no translation found for home_edu_toast_content (3381071147871955415) --> - <skip /> - <!-- no translation found for overview_edu_toast_content (5797030644017804518) --> - <skip /> - <!-- no translation found for all_apps_edu_toast_content (8807496014667211562) --> - <skip /> - <!-- no translation found for back_edu_notification_title (5624780717751357278) --> - <skip /> - <!-- no translation found for back_edu_notification_content (2497557451540954068) --> - <skip /> - <!-- no translation found for home_edu_notification_title (6097902076909654045) --> - <skip /> - <!-- no translation found for home_edu_notification_content (6631697734535766588) --> - <skip /> - <!-- no translation found for overview_edu_notification_title (1265824157319562406) --> - <skip /> - <!-- no translation found for overview_edu_notification_content (3578204677648432500) --> - <skip /> - <!-- no translation found for all_apps_edu_notification_title (372262997265569063) --> - <skip /> - <!-- no translation found for all_apps_edu_notification_content (3255070575694025585) --> - <skip /> + <string name="back_edu_toast_content" msgid="4530314597378982956">"כדי לחזור אחורה, מחליקים שמאלה או ימינה עם שלוש אצבעות על לוח המגע."</string> + <string name="home_edu_toast_content" msgid="3381071147871955415">"כדי לעבור למסך הבית, מחליקים למעלה עם שלוש אצבעות על לוח המגע"</string> + <string name="overview_edu_toast_content" msgid="5797030644017804518">"כדי לראות את האפליקציות האחרונות, מחליקים למעלה עם שלוש אצבעות על לוח המגע ולוחצים לחיצה ארוכה"</string> + <string name="all_apps_edu_toast_content" msgid="8807496014667211562">"כדי לראות את כל האפליקציות, מקישים על מקש הפעולה במקלדת"</string> + <string name="back_edu_notification_title" msgid="5624780717751357278">"איך להשתמש בלוח המגע כדי לחזור אחורה"</string> + <string name="back_edu_notification_content" msgid="2497557451540954068">"מחליקים ימינה או שמאלה עם שלוש אצבעות. ניתן להקיש כדי לקבל מידע נוסף על התנועות."</string> + <string name="home_edu_notification_title" msgid="6097902076909654045">"איך להשתמש בלוח המגע כדי לעבור למסך הבית"</string> + <string name="home_edu_notification_content" msgid="6631697734535766588">"מחליקים למעלה עם שלוש אצבעות. ניתן להקיש כדי לקבל מידע נוסף על התנועות."</string> + <string name="overview_edu_notification_title" msgid="1265824157319562406">"איך להשתמש בלוח המגע כדי לראות את האפליקציות האחרונות"</string> + <string name="overview_edu_notification_content" msgid="3578204677648432500">"מחליקים למעלה ולוחצים לחיצה ארוכה עם שלוש אצבעות. ניתן להקיש כדי לקבל מידע נוסף על התנועות."</string> + <string name="all_apps_edu_notification_title" msgid="372262997265569063">"איך להשתמש במקלדת כדי לראות את כל האפליקציות"</string> + <string name="all_apps_edu_notification_content" msgid="3255070575694025585">"בכל שלב אפשר ללחוץ על מקש הפעולה. ניתן להקיש כדי לקבל מידע נוסף על התנועות."</string> </resources> diff --git a/packages/SystemUI/res/values-iw/tiles_states_strings.xml b/packages/SystemUI/res/values-iw/tiles_states_strings.xml index 86edca8fca05..b5cb476484b2 100644 --- a/packages/SystemUI/res/values-iw/tiles_states_strings.xml +++ b/packages/SystemUI/res/values-iw/tiles_states_strings.xml @@ -56,11 +56,6 @@ <item msgid="5376619709702103243">"כבוי"</item> <item msgid="4875147066469902392">"פועל"</item> </string-array> - <string-array name="tile_states_modes"> - <item msgid="7764936419245199023">"לא זמין"</item> - <item msgid="2004750556637773692">"מצב מושבת"</item> - <item msgid="8968530753931637871">"מצב מופעל"</item> - </string-array> <string-array name="tile_states_flashlight"> <item msgid="3465257127433353857">"לא זמין"</item> <item msgid="5044688398303285224">"כבוי"</item> diff --git a/packages/SystemUI/res/values-ja/strings.xml b/packages/SystemUI/res/values-ja/strings.xml index 7a759980d953..7e09b94fec71 100644 --- a/packages/SystemUI/res/values-ja/strings.xml +++ b/packages/SystemUI/res/values-ja/strings.xml @@ -388,6 +388,9 @@ <string name="performance" msgid="6552785217174378320">"パフォーマンス"</string> <string name="user_interface" msgid="3712869377953950887">"ユーザー インターフェース"</string> <string name="thermal" msgid="6758074791325414831">"温度"</string> + <string name="custom" msgid="3337456985275158299">"カスタム"</string> + <string name="custom_trace_settings_dialog_title" msgid="2608570500144830554">"カスタム トレース設定"</string> + <string name="restore_default" msgid="5259420807486239755">"デフォルトに戻す"</string> <string name="quick_settings_onehanded_label" msgid="2416537930246274991">"片手モード"</string> <string name="quick_settings_hearing_devices_label" msgid="7277170419679404129">"補聴器"</string> <string name="quick_settings_hearing_devices_connected" msgid="6519069502397037781">"アクティブ"</string> @@ -431,6 +434,9 @@ <string name="zen_modes_dialog_settings" msgid="2310248023728936697">"設定"</string> <string name="zen_mode_on" msgid="9085304934016242591">"ON"</string> <string name="zen_mode_off" msgid="1736604456618147306">"OFF"</string> + <string name="zen_mode_set_up" msgid="7457957033034460064">"設定"</string> + <string name="zen_mode_no_manual_invocation" msgid="1769975741344633672">"設定で管理"</string> + <string name="zen_mode_active_modes" msgid="1625850411578488856">"{count,plural, =0{アクティブなモードはありません}=1{{mode} がアクティブです}other{# 個のモードがアクティブです}}"</string> <string name="zen_priority_introduction" msgid="3159291973383796646">"アラーム、リマインダー、予定、指定した人からの着信以外の音やバイブレーションに煩わされることはありません。音楽、動画、ゲームなど再生対象として選択したコンテンツは引き続き再生されます。"</string> <string name="zen_alarms_introduction" msgid="3987266042682300470">"アラーム以外の音やバイブレーションに煩わされることはありません。音楽、動画、ゲームなど再生対象として選択したコンテンツは引き続き再生されます。"</string> <string name="zen_priority_customize_button" msgid="4119213187257195047">"カスタマイズ"</string> @@ -469,6 +475,8 @@ <string name="keyguard_indication_charging_time_slowly" msgid="301936949731705417">"<xliff:g id="PERCENTAGE">%2$s</xliff:g> • 低速充電中 • 完了まで <xliff:g id="CHARGING_TIME_LEFT">%1$s</xliff:g>"</string> <string name="keyguard_indication_charging_time_dock" msgid="3149328898931741271">"<xliff:g id="PERCENTAGE">%2$s</xliff:g> • 充電中 • フル充電まで <xliff:g id="CHARGING_TIME_LEFT">%1$s</xliff:g>"</string> <string name="accessibility_action_open_communal_hub" msgid="3081702792413787849">"ロック画面のウィジェット"</string> + <!-- no translation found for accessibility_announcement_communal_widget_added (6911593106099328271) --> + <skip /> <string name="communal_tutorial_indicator_text" msgid="4503010353591430123">"左にスワイプすると、コミュニティ チュートリアルが開始します"</string> <string name="cta_tile_button_to_open_widget_editor" msgid="3871562362382963878">"カスタマイズ"</string> <string name="cta_tile_button_to_dismiss" msgid="3377597875997861754">"閉じる"</string> @@ -554,10 +562,8 @@ <string name="media_projection_action_text" msgid="3634906766918186440">"今すぐ開始"</string> <string name="empty_shade_text" msgid="8935967157319717412">"通知はありません"</string> <string name="no_unseen_notif_text" msgid="395512586119868682">"新しい通知はありません"</string> - <!-- no translation found for adaptive_notification_edu_hun_title (7790738150177329960) --> - <skip /> - <!-- no translation found for adaptive_notification_edu_hun_text (7743367744129536610) --> - <skip /> + <string name="adaptive_notification_edu_hun_title" msgid="7790738150177329960">"通知のクールダウンが ON になっています"</string> + <string name="adaptive_notification_edu_hun_text" msgid="7743367744129536610">"一度に多くの通知が届いたときに、最大 2 分間自動的にデバイスの音量が小さくなりアラートも減ります。"</string> <string name="go_to_adaptive_notification_settings" msgid="2423690125178298479">"OFF にする"</string> <string name="unlock_to_see_notif_text" msgid="7439033907167561227">"ロック解除して以前の通知を表示"</string> <string name="quick_settings_disclosure_parental_controls" msgid="2114102871438223600">"このデバイスは保護者によって管理されています"</string> @@ -1223,7 +1229,6 @@ <string name="accessibility_fingerprint_bouncer" msgid="7189102492498735519">"認証が必要です。指紋認証センサーをタッチして認証してください。"</string> <string name="ongoing_phone_call_content_description" msgid="5332334388483099947">"通話中"</string> <string name="mobile_data_settings_title" msgid="3955246641380064901">"モバイルデータ"</string> - <string name="preference_summary_default_combination" msgid="8453246369903749670">"<xliff:g id="STATE">%1$s</xliff:g> / <xliff:g id="NETWORKMODE">%2$s</xliff:g>"</string> <string name="mobile_data_connection_active" msgid="944490013299018227">"接続済み"</string> <string name="mobile_data_temp_connection_active" msgid="4590222725908806824">"一時的に接続されています"</string> <string name="mobile_data_poor_connection" msgid="819617772268371434">"接続が不安定です"</string> @@ -1377,7 +1382,10 @@ <string name="touchpad_tutorial_done_button" msgid="176168488821755503">"完了"</string> <string name="touchpad_tutorial_gesture_done" msgid="4784438360736821255">"よくできました。"</string> <string name="touchpad_back_gesture_action_title" msgid="7199067250654332735">"戻る"</string> - <string name="touchpad_back_gesture_guidance" msgid="4222430588599527272">"戻るには、3 本の指でタッチパッドを左右にスワイプします。"</string> + <!-- no translation found for touchpad_back_gesture_guidance (6263750214998421587) --> + <skip /> + <!-- no translation found for touchpad_back_gesture_finished (5353616006999726249) --> + <skip /> <string name="touchpad_back_gesture_animation_content_description" msgid="2646107450922379918">"タッチパッドで 3 本の指を左右に動かしている様子"</string> <string name="touchpad_back_gesture_screen_animation_content_description" msgid="4036267494237748710">"デバイスの画面で「戻る」ジェスチャーのアニメーションが表示されている様子"</string> <string name="keyboard_backlight_dialog_title" msgid="8273102932345564724">"キーボード バックライト"</string> diff --git a/packages/SystemUI/res/values-ja/tiles_states_strings.xml b/packages/SystemUI/res/values-ja/tiles_states_strings.xml index 6f85036016b7..790445c93c14 100644 --- a/packages/SystemUI/res/values-ja/tiles_states_strings.xml +++ b/packages/SystemUI/res/values-ja/tiles_states_strings.xml @@ -56,11 +56,6 @@ <item msgid="5376619709702103243">"OFF"</item> <item msgid="4875147066469902392">"ON"</item> </string-array> - <string-array name="tile_states_modes"> - <item msgid="7764936419245199023">"使用不可"</item> - <item msgid="2004750556637773692">"OFF"</item> - <item msgid="8968530753931637871">"ON"</item> - </string-array> <string-array name="tile_states_flashlight"> <item msgid="3465257127433353857">"使用不可"</item> <item msgid="5044688398303285224">"OFF"</item> diff --git a/packages/SystemUI/res/values-ka/strings.xml b/packages/SystemUI/res/values-ka/strings.xml index e6b2818320be..4d0e90cd8079 100644 --- a/packages/SystemUI/res/values-ka/strings.xml +++ b/packages/SystemUI/res/values-ka/strings.xml @@ -388,6 +388,9 @@ <string name="performance" msgid="6552785217174378320">"ეფექტურობა"</string> <string name="user_interface" msgid="3712869377953950887">"სამომხმარებლო ინტერფეისი"</string> <string name="thermal" msgid="6758074791325414831">"თერმული"</string> + <string name="custom" msgid="3337456985275158299">"მორგებული"</string> + <string name="custom_trace_settings_dialog_title" msgid="2608570500144830554">"თვალის დევნების მორგებული პარამეტრები"</string> + <string name="restore_default" msgid="5259420807486239755">"ნაგულისხმევის აღდგენა"</string> <string name="quick_settings_onehanded_label" msgid="2416537930246274991">"ცალი ხელის რეჟიმი"</string> <string name="quick_settings_hearing_devices_label" msgid="7277170419679404129">"სმენის აპარატები"</string> <string name="quick_settings_hearing_devices_connected" msgid="6519069502397037781">"აქტიური"</string> @@ -431,6 +434,12 @@ <string name="zen_modes_dialog_settings" msgid="2310248023728936697">"პარამეტრები"</string> <string name="zen_mode_on" msgid="9085304934016242591">"ჩართული"</string> <string name="zen_mode_off" msgid="1736604456618147306">"გამორთული"</string> + <!-- no translation found for zen_mode_set_up (7457957033034460064) --> + <skip /> + <!-- no translation found for zen_mode_no_manual_invocation (1769975741344633672) --> + <skip /> + <!-- no translation found for zen_mode_active_modes (1625850411578488856) --> + <skip /> <string name="zen_priority_introduction" msgid="3159291973383796646">"თქვენ მიერ მითითებული მაღვიძარების, შეხსენებების, მოვლენებისა და ზარების გარდა, არავითარი ხმა და ვიბრაცია არ შეგაწუხებთ. თქვენ მაინც შეძლებთ სასურველი კონტენტის, მაგალითად, მუსიკის, ვიდეოებისა და თამაშების აუდიოს მოსმენა."</string> <string name="zen_alarms_introduction" msgid="3987266042682300470">"მაღვიძარების გარდა, არავითარი ხმა და ვიბრაცია არ შეგაწუხებთ. თქვენ მაინც შეძლებთ სასურველი კონტენტის, მაგალითად, მუსიკის, ვიდეოებისა და თამაშების აუდიოს მოსმენა."</string> <string name="zen_priority_customize_button" msgid="4119213187257195047">"მორგება"</string> @@ -469,6 +478,8 @@ <string name="keyguard_indication_charging_time_slowly" msgid="301936949731705417">"<xliff:g id="PERCENTAGE">%2$s</xliff:g> • ნელა იტენება • სრულ დატენვამდე <xliff:g id="CHARGING_TIME_LEFT">%1$s</xliff:g>"</string> <string name="keyguard_indication_charging_time_dock" msgid="3149328898931741271">"<xliff:g id="PERCENTAGE">%2$s</xliff:g> • იტენება • სრულ დატენვამდე <xliff:g id="CHARGING_TIME_LEFT">%1$s</xliff:g>"</string> <string name="accessibility_action_open_communal_hub" msgid="3081702792413787849">"ვიჯეტები ჩაკეტილ ეკრანზე"</string> + <!-- no translation found for accessibility_announcement_communal_widget_added (6911593106099328271) --> + <skip /> <string name="communal_tutorial_indicator_text" msgid="4503010353591430123">"გადაფურცლეთ მარცხნივ, რათა დაიწყოთ საერთო სახელმძღვანელო"</string> <string name="cta_tile_button_to_open_widget_editor" msgid="3871562362382963878">"მორგება"</string> <string name="cta_tile_button_to_dismiss" msgid="3377597875997861754">"უარყოფა"</string> @@ -554,10 +565,8 @@ <string name="media_projection_action_text" msgid="3634906766918186440">"დაწყება ახლავე"</string> <string name="empty_shade_text" msgid="8935967157319717412">"შეტყობინებები არ არის."</string> <string name="no_unseen_notif_text" msgid="395512586119868682">"ახალი შეტყობინებები არ არის"</string> - <!-- no translation found for adaptive_notification_edu_hun_title (7790738150177329960) --> - <skip /> - <!-- no translation found for adaptive_notification_edu_hun_text (7743367744129536610) --> - <skip /> + <string name="adaptive_notification_edu_hun_title" msgid="7790738150177329960">"შეტყობინების განტვირთვის პერიოდი ჩართულია"</string> + <string name="adaptive_notification_edu_hun_text" msgid="7743367744129536610">"მოწყობილობის ხმა და გაფრთხილებები მცირდება 2 წუთის განმავლობაში, როდესაც ბევრ შეტყობინებას მიიღებთ ერთდროულად."</string> <string name="go_to_adaptive_notification_settings" msgid="2423690125178298479">"გამორთვა"</string> <string name="unlock_to_see_notif_text" msgid="7439033907167561227">"განბლოკეთ ძველი შეტყობინებების სანახავად"</string> <string name="quick_settings_disclosure_parental_controls" msgid="2114102871438223600">"მოწყობილობას თქვენი მშობელი მართავს"</string> @@ -1223,7 +1232,6 @@ <string name="accessibility_fingerprint_bouncer" msgid="7189102492498735519">"საჭიროა ავტორიზაცია. ავტორიზაციისთვის შეეხეთ თითის ანაბეჭდის სენსორს."</string> <string name="ongoing_phone_call_content_description" msgid="5332334388483099947">"მიმდინარე სატელეფონო ზარი"</string> <string name="mobile_data_settings_title" msgid="3955246641380064901">"მობილური ინტერნეტი"</string> - <string name="preference_summary_default_combination" msgid="8453246369903749670">"<xliff:g id="STATE">%1$s</xliff:g> / <xliff:g id="NETWORKMODE">%2$s</xliff:g>"</string> <string name="mobile_data_connection_active" msgid="944490013299018227">"დაკავშირებული"</string> <string name="mobile_data_temp_connection_active" msgid="4590222725908806824">"დროებით დაკავშირებული"</string> <string name="mobile_data_poor_connection" msgid="819617772268371434">"სუსტი კავშირი"</string> @@ -1377,7 +1385,10 @@ <string name="touchpad_tutorial_done_button" msgid="176168488821755503">"მზადაა"</string> <string name="touchpad_tutorial_gesture_done" msgid="4784438360736821255">"შესანიშნავია!"</string> <string name="touchpad_back_gesture_action_title" msgid="7199067250654332735">"უკან დაბრუნება"</string> - <string name="touchpad_back_gesture_guidance" msgid="4222430588599527272">"უკან დასაბრუნებლად, სენსორულ პანელზე ნებისმიერ ადგილას სამი თითის გამოყენებით გადაფურცლეთ მარცხნივ ან მარჯვნივ."</string> + <!-- no translation found for touchpad_back_gesture_guidance (6263750214998421587) --> + <skip /> + <!-- no translation found for touchpad_back_gesture_finished (5353616006999726249) --> + <skip /> <string name="touchpad_back_gesture_animation_content_description" msgid="2646107450922379918">"სენსორული პანელი, რომელიც აჩვენებს მარჯვენა და მარცხენა მიმართულებით მოძრავ სამ თითს"</string> <string name="touchpad_back_gesture_screen_animation_content_description" msgid="4036267494237748710">"მოწყობილობის ეკრანი, რომელიც აჩვენებს უკან დაბრუნების ჟესტის ანიმაციას"</string> <string name="keyboard_backlight_dialog_title" msgid="8273102932345564724">"კლავიატურის შენათება"</string> diff --git a/packages/SystemUI/res/values-ka/tiles_states_strings.xml b/packages/SystemUI/res/values-ka/tiles_states_strings.xml index 2b11a15aee7e..21f8102036c9 100644 --- a/packages/SystemUI/res/values-ka/tiles_states_strings.xml +++ b/packages/SystemUI/res/values-ka/tiles_states_strings.xml @@ -56,11 +56,6 @@ <item msgid="5376619709702103243">"გამორთულია"</item> <item msgid="4875147066469902392">"ჩართულია"</item> </string-array> - <string-array name="tile_states_modes"> - <item msgid="7764936419245199023">"მიუწვდომელია"</item> - <item msgid="2004750556637773692">"გამორთული"</item> - <item msgid="8968530753931637871">"ჩართული"</item> - </string-array> <string-array name="tile_states_flashlight"> <item msgid="3465257127433353857">"მიუწვდომელია"</item> <item msgid="5044688398303285224">"გამორთულია"</item> diff --git a/packages/SystemUI/res/values-kk/strings.xml b/packages/SystemUI/res/values-kk/strings.xml index 6415aa13a46f..9d84c730aa95 100644 --- a/packages/SystemUI/res/values-kk/strings.xml +++ b/packages/SystemUI/res/values-kk/strings.xml @@ -388,6 +388,9 @@ <string name="performance" msgid="6552785217174378320">"Өнімділік"</string> <string name="user_interface" msgid="3712869377953950887">"Пайдаланушы интерфейсі"</string> <string name="thermal" msgid="6758074791325414831">"Термовизия"</string> + <string name="custom" msgid="3337456985275158299">"Басқа"</string> + <string name="custom_trace_settings_dialog_title" msgid="2608570500144830554">"Басқа трассалау параметрлері"</string> + <string name="restore_default" msgid="5259420807486239755">"Әдепкі қалпына келтіру"</string> <string name="quick_settings_onehanded_label" msgid="2416537930246274991">"Бір қолмен басқару режимі"</string> <string name="quick_settings_hearing_devices_label" msgid="7277170419679404129">"Есту құрылғылары"</string> <string name="quick_settings_hearing_devices_connected" msgid="6519069502397037781">"Қосулы"</string> @@ -429,9 +432,13 @@ <string name="zen_modes_dialog_title" msgid="4159138230418567383">"Басымдық режимдері"</string> <string name="zen_modes_dialog_done" msgid="6654130880256438950">"Дайын"</string> <string name="zen_modes_dialog_settings" msgid="2310248023728936697">"Параметрлер"</string> - <!-- no translation found for zen_mode_on (9085304934016242591) --> + <string name="zen_mode_on" msgid="9085304934016242591">"Қосулы"</string> + <string name="zen_mode_off" msgid="1736604456618147306">"Өшірулі"</string> + <!-- no translation found for zen_mode_set_up (7457957033034460064) --> <skip /> - <!-- no translation found for zen_mode_off (1736604456618147306) --> + <!-- no translation found for zen_mode_no_manual_invocation (1769975741344633672) --> + <skip /> + <!-- no translation found for zen_mode_active_modes (1625850411578488856) --> <skip /> <string name="zen_priority_introduction" msgid="3159291973383796646">"Оятқыш, еске салғыш, іс-шара мен өзіңіз көрсеткен контактілердің қоңырауларынан басқа дыбыстар мен дірілдер мазаламайтын болады. Музыка, бейне және ойын сияқты медиафайлдарды қоссаңыз, оларды естисіз."</string> <string name="zen_alarms_introduction" msgid="3987266042682300470">"Дабылдардан басқа ешқандай дыбыстар мен дірілдер мазаламайтын болады. Музыка, бейне және ойындар сияқты ойнатылатын контентті ести алатын боласыз."</string> @@ -471,6 +478,8 @@ <string name="keyguard_indication_charging_time_slowly" msgid="301936949731705417">"<xliff:g id="PERCENTAGE">%2$s</xliff:g> • Баяу зарядталуда • Толуына <xliff:g id="CHARGING_TIME_LEFT">%1$s</xliff:g> қалды."</string> <string name="keyguard_indication_charging_time_dock" msgid="3149328898931741271">"<xliff:g id="PERCENTAGE">%2$s</xliff:g> • Зарядталып жатыр. • Толуына <xliff:g id="CHARGING_TIME_LEFT">%1$s</xliff:g> қалды."</string> <string name="accessibility_action_open_communal_hub" msgid="3081702792413787849">"Құлыптаулы экрандағы виджеттер"</string> + <!-- no translation found for accessibility_announcement_communal_widget_added (6911593106099328271) --> + <skip /> <string name="communal_tutorial_indicator_text" msgid="4503010353591430123">"Ортақ оқулықты ашу үшін солға қарай сырғытыңыз."</string> <string name="cta_tile_button_to_open_widget_editor" msgid="3871562362382963878">"Бейімдеу"</string> <string name="cta_tile_button_to_dismiss" msgid="3377597875997861754">"Жабу"</string> @@ -499,8 +508,7 @@ <string name="accessibility_action_label_place_widget" msgid="1914197458644168978">"таңдалған виджетті орналастыру"</string> <string name="communal_widget_picker_title" msgid="1953369090475731663">"Құлып экранының виджеттері"</string> <string name="communal_widget_picker_description" msgid="490515450110487871">"Планшет құлыпталып тұрса да, құлып экранындағы виджеттерді кез келген адам көре алады."</string> - <!-- no translation found for accessibility_action_label_unselect_widget (1041811747619468698) --> - <skip /> + <string name="accessibility_action_label_unselect_widget" msgid="1041811747619468698">"виджетті таңдаудан алу"</string> <string name="communal_widgets_disclaimer_title" msgid="1150954395585308868">"Құлып экранының виджеттері"</string> <string name="communal_widgets_disclaimer_text" msgid="1423545475160506349">"Қолданбаны виджет көмегімен ашу үшін жеке басыңызды растауыңыз керек. Сондай-ақ басқалар оларды планшетіңіз құлыптаулы кезде де көре алатынын ескеріңіз. Кейбір виджеттер құлып экранына арналмаған болады, сондықтан оларды мұнда қосу қауіпсіз болмауы мүмкін."</string> <string name="communal_widgets_disclaimer_button" msgid="4423059765740780753">"Түсінікті"</string> @@ -557,10 +565,8 @@ <string name="media_projection_action_text" msgid="3634906766918186440">"Қазір бастау"</string> <string name="empty_shade_text" msgid="8935967157319717412">"Хабарландырулар жоқ"</string> <string name="no_unseen_notif_text" msgid="395512586119868682">"Жаңа хабарландырулар жоқ"</string> - <!-- no translation found for adaptive_notification_edu_hun_title (7790738150177329960) --> - <skip /> - <!-- no translation found for adaptive_notification_edu_hun_text (7743367744129536610) --> - <skip /> + <string name="adaptive_notification_edu_hun_title" msgid="7790738150177329960">"Хабарландыру дыбысын азайту параметрі қосулы"</string> + <string name="adaptive_notification_edu_hun_text" msgid="7743367744129536610">"Бір уақытта тым көп хабарландыру келсе, дыбыс деңгейі автоматты түрде азайтылып, хабарландырулар 2 минутқа кідіртіледі."</string> <string name="go_to_adaptive_notification_settings" msgid="2423690125178298479">"Өшіру"</string> <string name="unlock_to_see_notif_text" msgid="7439033907167561227">"Ескі хабарландырулар үшін құлыпты ашыңыз"</string> <string name="quick_settings_disclosure_parental_controls" msgid="2114102871438223600">"Бұл құрылғыны ата-анаңыз басқарады."</string> @@ -1226,7 +1232,6 @@ <string name="accessibility_fingerprint_bouncer" msgid="7189102492498735519">"Аутентификациядан өту қажет. Ол үшін саусақ ізін оқу сканерін түртіңіз."</string> <string name="ongoing_phone_call_content_description" msgid="5332334388483099947">"Телефон қоңырауы бар"</string> <string name="mobile_data_settings_title" msgid="3955246641380064901">"Мобильдік интернет"</string> - <string name="preference_summary_default_combination" msgid="8453246369903749670">"<xliff:g id="STATE">%1$s</xliff:g>/<xliff:g id="NETWORKMODE">%2$s</xliff:g>"</string> <string name="mobile_data_connection_active" msgid="944490013299018227">"Жалғанды"</string> <string name="mobile_data_temp_connection_active" msgid="4590222725908806824">"Уақытша байланыс орнатылды."</string> <string name="mobile_data_poor_connection" msgid="819617772268371434">"Байланыс нашар."</string> @@ -1380,7 +1385,10 @@ <string name="touchpad_tutorial_done_button" msgid="176168488821755503">"Дайын"</string> <string name="touchpad_tutorial_gesture_done" msgid="4784438360736821255">"Жарайсыз!"</string> <string name="touchpad_back_gesture_action_title" msgid="7199067250654332735">"Артқа"</string> - <string name="touchpad_back_gesture_guidance" msgid="4222430588599527272">"Артқа қайту үшін сенсорлық тақтаның кез келген жерінен үш саусақпен солға немесе оңға сырғытыңыз."</string> + <!-- no translation found for touchpad_back_gesture_guidance (6263750214998421587) --> + <skip /> + <!-- no translation found for touchpad_back_gesture_finished (5353616006999726249) --> + <skip /> <string name="touchpad_back_gesture_animation_content_description" msgid="2646107450922379918">"Оңға және солға жылжитын үш саусақты көрсетіп тұрған сенсорлық тақта."</string> <string name="touchpad_back_gesture_screen_animation_content_description" msgid="4036267494237748710">"Артқа қайту қимылын көрсетіп тұрған құрылғы экраны."</string> <string name="keyboard_backlight_dialog_title" msgid="8273102932345564724">"Пернетақта жарығы"</string> @@ -1388,28 +1396,16 @@ <string name="home_controls_dream_label" msgid="6567105701292324257">"Үй басқару элементтері"</string> <string name="home_controls_dream_description" msgid="4644150952104035789">"Үй басқару элементтерін скринсейверден қолданыңыз."</string> <string name="volume_undo_action" msgid="5815519725211877114">"Қайтару"</string> - <!-- no translation found for back_edu_toast_content (4530314597378982956) --> - <skip /> - <!-- no translation found for home_edu_toast_content (3381071147871955415) --> - <skip /> - <!-- no translation found for overview_edu_toast_content (5797030644017804518) --> - <skip /> - <!-- no translation found for all_apps_edu_toast_content (8807496014667211562) --> - <skip /> - <!-- no translation found for back_edu_notification_title (5624780717751357278) --> - <skip /> - <!-- no translation found for back_edu_notification_content (2497557451540954068) --> - <skip /> - <!-- no translation found for home_edu_notification_title (6097902076909654045) --> - <skip /> - <!-- no translation found for home_edu_notification_content (6631697734535766588) --> - <skip /> - <!-- no translation found for overview_edu_notification_title (1265824157319562406) --> - <skip /> - <!-- no translation found for overview_edu_notification_content (3578204677648432500) --> - <skip /> - <!-- no translation found for all_apps_edu_notification_title (372262997265569063) --> - <skip /> - <!-- no translation found for all_apps_edu_notification_content (3255070575694025585) --> - <skip /> + <string name="back_edu_toast_content" msgid="4530314597378982956">"Сенсорлық тақтада үш саусақпен солға не оңға сырғытсаңыз, артқа қайтасыз."</string> + <string name="home_edu_toast_content" msgid="3381071147871955415">"Сенсорлық сақтада үш саусақпен жоғары сырғытсаңыз, негізгі бетке өтесіз."</string> + <string name="overview_edu_toast_content" msgid="5797030644017804518">"Сенсорлық тақтада үш саусақпен жоғары сырғытып, басып тұрсаңыз, соңғы ашылған қолданбаларды көресіз."</string> + <string name="all_apps_edu_toast_content" msgid="8807496014667211562">"Пернетақтада әрекет пернесін басып, барлық қолданбаны көре аласыз."</string> + <string name="back_edu_notification_title" msgid="5624780717751357278">"Артқа қайту үшін сенсорлық тақтаны қолданыңыз"</string> + <string name="back_edu_notification_content" msgid="2497557451540954068">"Үш саусақпен солға не оңға сырғытыңыз. Басқа қимылдарды үйрену үшін түртіңіз."</string> + <string name="home_edu_notification_title" msgid="6097902076909654045">"Негізгі бетке өту үшін сенсорлық тақтаны қолданыңыз"</string> + <string name="home_edu_notification_content" msgid="6631697734535766588">"Үш саусақпен жоғары сырғытыңыз. Басқа қимылдарды үйрену үшін түртіңіз."</string> + <string name="overview_edu_notification_title" msgid="1265824157319562406">"Соңғы ашылған қолданбаларды көру үшін сенсорлық тақтаны қолданыңыз"</string> + <string name="overview_edu_notification_content" msgid="3578204677648432500">"Үш саусақпен жоғары сырғытып, басып тұрыңыз. Басқа қимылдарды үйрену үшін түртіңіз."</string> + <string name="all_apps_edu_notification_title" msgid="372262997265569063">"Барлық қолданбаны көру үшін пернетақтаны қолданыңыз"</string> + <string name="all_apps_edu_notification_content" msgid="3255070575694025585">"Әрекет пернесін кез келген уақытта баса аласыз. Басқа қимылдарды үйрену үшін түртіңіз."</string> </resources> diff --git a/packages/SystemUI/res/values-kk/tiles_states_strings.xml b/packages/SystemUI/res/values-kk/tiles_states_strings.xml index 94a9806449fc..cf3aa69992f1 100644 --- a/packages/SystemUI/res/values-kk/tiles_states_strings.xml +++ b/packages/SystemUI/res/values-kk/tiles_states_strings.xml @@ -56,11 +56,6 @@ <item msgid="5376619709702103243">"Өшірулі"</item> <item msgid="4875147066469902392">"Қосулы"</item> </string-array> - <string-array name="tile_states_modes"> - <item msgid="7764936419245199023">"Қолжетімді емес"</item> - <item msgid="2004750556637773692">"Өшірулі"</item> - <item msgid="8968530753931637871">"Қосулы"</item> - </string-array> <string-array name="tile_states_flashlight"> <item msgid="3465257127433353857">"Қолжетімсіз"</item> <item msgid="5044688398303285224">"Өшірулі"</item> diff --git a/packages/SystemUI/res/values-km/strings.xml b/packages/SystemUI/res/values-km/strings.xml index a85e4b55a7b5..b84b6b6e9d87 100644 --- a/packages/SystemUI/res/values-km/strings.xml +++ b/packages/SystemUI/res/values-km/strings.xml @@ -388,6 +388,9 @@ <string name="performance" msgid="6552785217174378320">"ប្រតិបត្តិការ"</string> <string name="user_interface" msgid="3712869377953950887">"ផ្ទៃប៉ះ"</string> <string name="thermal" msgid="6758074791325414831">"កម្ដៅ"</string> + <string name="custom" msgid="3337456985275158299">"ផ្ទាល់ខ្លួន"</string> + <string name="custom_trace_settings_dialog_title" msgid="2608570500144830554">"ការកំណត់ដានផ្ទាល់ខ្លួន"</string> + <string name="restore_default" msgid="5259420807486239755">"ស្ដារទៅលំនាំដើម"</string> <string name="quick_settings_onehanded_label" msgid="2416537930246274991">"មុខងារប្រើដៃម្ខាង"</string> <string name="quick_settings_hearing_devices_label" msgid="7277170419679404129">"ឧបករណ៍ជំនួយការស្ដាប់"</string> <string name="quick_settings_hearing_devices_connected" msgid="6519069502397037781">"សកម្ម"</string> @@ -429,9 +432,13 @@ <string name="zen_modes_dialog_title" msgid="4159138230418567383">"មុខងារអាទិភាព"</string> <string name="zen_modes_dialog_done" msgid="6654130880256438950">"រួចរាល់"</string> <string name="zen_modes_dialog_settings" msgid="2310248023728936697">"ការកំណត់"</string> - <!-- no translation found for zen_mode_on (9085304934016242591) --> + <string name="zen_mode_on" msgid="9085304934016242591">"បើក"</string> + <string name="zen_mode_off" msgid="1736604456618147306">"បិទ"</string> + <!-- no translation found for zen_mode_set_up (7457957033034460064) --> <skip /> - <!-- no translation found for zen_mode_off (1736604456618147306) --> + <!-- no translation found for zen_mode_no_manual_invocation (1769975741344633672) --> + <skip /> + <!-- no translation found for zen_mode_active_modes (1625850411578488856) --> <skip /> <string name="zen_priority_introduction" msgid="3159291973383796646">"សំឡេង និងរំញ័រនឹងមិនរំខានដល់អ្នកឡើយ លើកលែងតែម៉ោងរោទ៍ ការរំលឹក ព្រឹត្តិការណ៍ និងអ្នកហៅទូរសព្ទដែលអ្នកបញ្ជាក់ប៉ុណ្ណោះ។ អ្នកនឹងនៅតែឮសំឡេងសកម្មភាពគ្រប់យ៉ាងដែលអ្នកលេងដដែល រួមទាំងតន្រ្តី វីដេអូ និងហ្គេម។"</string> <string name="zen_alarms_introduction" msgid="3987266042682300470">"សំឡេង និងរំញ័រនឹងមិនរំខានដល់អ្នកឡើយ លើកលែងតែម៉ោងរោទ៍ប៉ុណ្ណោះ។ អ្នកនឹងនៅតែឮសំឡេងសកម្មភាពគ្រប់យ៉ាងដែលអ្នកលេងដដែល រួមទាំងតន្រ្តី វីដេអូ និងហ្គេម។"</string> @@ -471,6 +478,8 @@ <string name="keyguard_indication_charging_time_slowly" msgid="301936949731705417">"<xliff:g id="PERCENTAGE">%2$s</xliff:g> • កំពុងសាកថ្មយឺត • ពេញក្នុងរយៈពេល <xliff:g id="CHARGING_TIME_LEFT">%1$s</xliff:g>"</string> <string name="keyguard_indication_charging_time_dock" msgid="3149328898931741271">"<xliff:g id="PERCENTAGE">%2$s</xliff:g> • កំពុងសាកថ្ម • ពេញក្នុងរយៈពេល <xliff:g id="CHARGING_TIME_LEFT">%1$s</xliff:g>"</string> <string name="accessibility_action_open_communal_hub" msgid="3081702792413787849">"ធាតុក្រាហ្វិកនៅលើអេក្រង់ចាក់សោ"</string> + <!-- no translation found for accessibility_announcement_communal_widget_added (6911593106099328271) --> + <skip /> <string name="communal_tutorial_indicator_text" msgid="4503010353591430123">"អូសទៅឆ្វេង ដើម្បីចាប់ផ្ដើមមេរៀនសហគមន៍"</string> <string name="cta_tile_button_to_open_widget_editor" msgid="3871562362382963878">"ប្ដូរតាមបំណង"</string> <string name="cta_tile_button_to_dismiss" msgid="3377597875997861754">"ច្រានចោល"</string> @@ -499,8 +508,7 @@ <string name="accessibility_action_label_place_widget" msgid="1914197458644168978">"ដាក់ធាតុក្រាហ្វិកដែលបានជ្រើសរើស"</string> <string name="communal_widget_picker_title" msgid="1953369090475731663">"ធាតុក្រាហ្វិកអេក្រង់ចាក់សោ"</string> <string name="communal_widget_picker_description" msgid="490515450110487871">"អ្នកគ្រប់គ្នាអាចមើលធាតុក្រាហ្វិកលើអេក្រង់ចាក់សោរបស់អ្នក ទោះបីជាថេប្លេតរបស់អ្នកត្រូវបានចាក់សោក៏ដោយ។"</string> - <!-- no translation found for accessibility_action_label_unselect_widget (1041811747619468698) --> - <skip /> + <string name="accessibility_action_label_unselect_widget" msgid="1041811747619468698">"ដកការជ្រើសរើសធាតុក្រាហ្វិក"</string> <string name="communal_widgets_disclaimer_title" msgid="1150954395585308868">"ធាតុក្រាហ្វិកលើអេក្រង់ចាក់សោ"</string> <string name="communal_widgets_disclaimer_text" msgid="1423545475160506349">"ដើម្បីបើកកម្មវិធីដោយប្រើធាតុក្រាហ្វិក អ្នកនឹងត្រូវផ្ទៀងផ្ទាត់ថាជាអ្នក។ ទន្ទឹមនឹងនេះ សូមចងចាំថា នរណាក៏អាចមើលធាតុក្រាហ្វិកបាន សូម្បីពេលថេប្លេតរបស់អ្នកជាប់សោក៏ដោយ។ ធាតុក្រាហ្វិកមួយចំនួនប្រហែលមិនត្រូវបានរចនាឡើងសម្រាប់អេក្រង់ចាក់សោរបស់អ្នកទេ និងមិនមានសុវត្ថិភាពឡើយ បើបញ្ចូលទៅទីនេះ។"</string> <string name="communal_widgets_disclaimer_button" msgid="4423059765740780753">"យល់ហើយ"</string> @@ -557,10 +565,8 @@ <string name="media_projection_action_text" msgid="3634906766918186440">"ចាប់ផ្ដើមឥឡូវ"</string> <string name="empty_shade_text" msgid="8935967157319717412">"គ្មានការជូនដំណឹង"</string> <string name="no_unseen_notif_text" msgid="395512586119868682">"គ្មានការជូនដំណឹងថ្មីៗទេ"</string> - <!-- no translation found for adaptive_notification_edu_hun_title (7790738150177329960) --> - <skip /> - <!-- no translation found for adaptive_notification_edu_hun_text (7743367744129536610) --> - <skip /> + <string name="adaptive_notification_edu_hun_title" msgid="7790738150177329960">"ការបន្ថយសំឡេងការជូនដំណឹងត្រូវបានបើក"</string> + <string name="adaptive_notification_edu_hun_text" msgid="7743367744129536610">"កម្រិតសំឡេង និងការជូនដំណឹងនៅលើឧបករណ៍របស់អ្នកត្រូវបានកាត់បន្ថយដោយស្វ័យប្រវត្តិរហូតដល់ 2 នាទី នៅពេលអ្នកទទួលបានការជូនដំណឹងច្រើនពេកក្នុងពេលតែមួយ។"</string> <string name="go_to_adaptive_notification_settings" msgid="2423690125178298479">"បិទ"</string> <string name="unlock_to_see_notif_text" msgid="7439033907167561227">"ដោះសោដើម្បីមើលការជូនដំណឹងចាស់ៗ"</string> <string name="quick_settings_disclosure_parental_controls" msgid="2114102871438223600">"ឧបករណ៍នេះស្ថិតក្រោមការគ្រប់គ្រងរបស់មាតាបិតាអ្នក"</string> @@ -1226,7 +1232,6 @@ <string name="accessibility_fingerprint_bouncer" msgid="7189102492498735519">"តម្រូវឱ្យមានការផ្ទៀងផ្ទាត់។ សូមចុចឧបករណ៍ចាប់ស្នាមម្រាមដៃ ដើម្បីផ្ទៀងផ្ទាត់។"</string> <string name="ongoing_phone_call_content_description" msgid="5332334388483099947">"ការហៅទូរសព្ទដែលកំពុងដំណើរការ"</string> <string name="mobile_data_settings_title" msgid="3955246641380064901">"ទិន្នន័យទូរសព្ទចល័ត"</string> - <string name="preference_summary_default_combination" msgid="8453246369903749670">"<xliff:g id="STATE">%1$s</xliff:g> / <xliff:g id="NETWORKMODE">%2$s</xliff:g>"</string> <string name="mobile_data_connection_active" msgid="944490013299018227">"បានភ្ជាប់"</string> <string name="mobile_data_temp_connection_active" msgid="4590222725908806824">"បានភ្ជាប់ជាបណ្ដោះអាសន្ន"</string> <string name="mobile_data_poor_connection" msgid="819617772268371434">"ការតភ្ជាប់ខ្សោយ"</string> @@ -1380,7 +1385,10 @@ <string name="touchpad_tutorial_done_button" msgid="176168488821755503">"រួចរាល់"</string> <string name="touchpad_tutorial_gesture_done" msgid="4784438360736821255">"ធ្វើបានល្អ!"</string> <string name="touchpad_back_gesture_action_title" msgid="7199067250654332735">"ថយក្រោយ"</string> - <string name="touchpad_back_gesture_guidance" msgid="4222430588599527272">"ដើម្បីថយក្រោយ សូមអូសទៅឆ្វេង ឬស្ដាំដោយប្រើម្រាមដៃបីនៅកន្លែងណាមួយនៅលើផ្ទាំងប៉ះ។"</string> + <!-- no translation found for touchpad_back_gesture_guidance (6263750214998421587) --> + <skip /> + <!-- no translation found for touchpad_back_gesture_finished (5353616006999726249) --> + <skip /> <string name="touchpad_back_gesture_animation_content_description" msgid="2646107450922379918">"ផ្ទាំងប៉ះដែលបង្ហាញម្រាមដៃបីដែលផ្លាស់ទីទៅស្ដាំ និងឆ្វេង"</string> <string name="touchpad_back_gesture_screen_animation_content_description" msgid="4036267494237748710">"អេក្រង់ឧបករណ៍ដែលបង្ហាញរូបមានចលនាសម្រាប់ចលនាថយក្រោយ"</string> <string name="keyboard_backlight_dialog_title" msgid="8273102932345564724">"ពន្លឺក្រោយក្ដារចុច"</string> @@ -1388,28 +1396,16 @@ <string name="home_controls_dream_label" msgid="6567105701292324257">"ការគ្រប់គ្រងផ្ទះ"</string> <string name="home_controls_dream_description" msgid="4644150952104035789">"ចូលប្រើការគ្រប់គ្រងផ្ទះអ្នកបានលឿនជាធាតុរក្សាអេក្រង់"</string> <string name="volume_undo_action" msgid="5815519725211877114">"ត្រឡប់វិញ"</string> - <!-- no translation found for back_edu_toast_content (4530314597378982956) --> - <skip /> - <!-- no translation found for home_edu_toast_content (3381071147871955415) --> - <skip /> - <!-- no translation found for overview_edu_toast_content (5797030644017804518) --> - <skip /> - <!-- no translation found for all_apps_edu_toast_content (8807496014667211562) --> - <skip /> - <!-- no translation found for back_edu_notification_title (5624780717751357278) --> - <skip /> - <!-- no translation found for back_edu_notification_content (2497557451540954068) --> - <skip /> - <!-- no translation found for home_edu_notification_title (6097902076909654045) --> - <skip /> - <!-- no translation found for home_edu_notification_content (6631697734535766588) --> - <skip /> - <!-- no translation found for overview_edu_notification_title (1265824157319562406) --> - <skip /> - <!-- no translation found for overview_edu_notification_content (3578204677648432500) --> - <skip /> - <!-- no translation found for all_apps_edu_notification_title (372262997265569063) --> - <skip /> - <!-- no translation found for all_apps_edu_notification_content (3255070575694025585) --> - <skip /> + <string name="back_edu_toast_content" msgid="4530314597378982956">"ដើម្បីថយក្រោយ សូមអូសទៅឆ្វេង ឬស្ដាំដោយប្រើម្រាមដៃបីនៅលើផ្ទាំងប៉ះ"</string> + <string name="home_edu_toast_content" msgid="3381071147871955415">"ដើម្បីចូលទៅទំព័រដើម សូមអូសឡើងលើដោយប្រើម្រាមដៃបីនៅលើផ្ទាំងប៉ះ"</string> + <string name="overview_edu_toast_content" msgid="5797030644017804518">"ដើម្បីមើលកម្មវិធីថ្មីៗ សូមអូសឡើងលើ ហើយសង្កត់ឱ្យជាប់ដោយប្រើម្រាមដៃបីនៅលើផ្ទាំងប៉ះ"</string> + <string name="all_apps_edu_toast_content" msgid="8807496014667211562">"ដើម្បីមើលកម្មវិធីទាំងអស់របស់អ្នក សូមចុចគ្រាប់ចុចសកម្មភាពនៅលើក្ដារចុចរបស់អ្នក"</string> + <string name="back_edu_notification_title" msgid="5624780717751357278">"ប្រើផ្ទាំងប៉ះរបស់អ្នក ដើម្បីថយក្រោយ"</string> + <string name="back_edu_notification_content" msgid="2497557451540954068">"អូសទៅឆ្វេង ឬស្ដាំដោយប្រើម្រាមដៃបី។ ចុច ដើម្បីស្វែងយល់បន្ថែមអំពីចលនា។"</string> + <string name="home_edu_notification_title" msgid="6097902076909654045">"ប្រើផ្ទាំងប៉ះរបស់អ្នក ដើម្បីចូលទៅទំព័រដើម"</string> + <string name="home_edu_notification_content" msgid="6631697734535766588">"អូសឡើងលើដោយប្រើម្រាមដៃបី។ ចុច ដើម្បីស្វែងយល់បន្ថែមអំពីចលនា។"</string> + <string name="overview_edu_notification_title" msgid="1265824157319562406">"ប្រើផ្ទាំងប៉ះរបស់អ្នក ដើម្បីមើលកម្មវិធីថ្មីៗ"</string> + <string name="overview_edu_notification_content" msgid="3578204677648432500">"អូសឡើងលើ ហើយសង្កត់ឱ្យជាប់ដោយប្រើម្រាមដៃបី។ ចុច ដើម្បីស្វែងយល់បន្ថែមអំពីចលនា។"</string> + <string name="all_apps_edu_notification_title" msgid="372262997265569063">"ប្រើក្ដារចុចរបស់អ្នក ដើម្បីមើលកម្មវិធីទាំងអស់"</string> + <string name="all_apps_edu_notification_content" msgid="3255070575694025585">"ចុចគ្រាប់ចុចសកម្មភាពនៅពេលណាក៏បាន។ ចុច ដើម្បីស្វែងយល់បន្ថែមអំពីចលនា។"</string> </resources> diff --git a/packages/SystemUI/res/values-km/tiles_states_strings.xml b/packages/SystemUI/res/values-km/tiles_states_strings.xml index 11e2c2a896ff..54790f6a028e 100644 --- a/packages/SystemUI/res/values-km/tiles_states_strings.xml +++ b/packages/SystemUI/res/values-km/tiles_states_strings.xml @@ -56,11 +56,6 @@ <item msgid="5376619709702103243">"បិទ"</item> <item msgid="4875147066469902392">"បើក"</item> </string-array> - <string-array name="tile_states_modes"> - <item msgid="7764936419245199023">"មិនមានទេ"</item> - <item msgid="2004750556637773692">"បិទ"</item> - <item msgid="8968530753931637871">"បើក"</item> - </string-array> <string-array name="tile_states_flashlight"> <item msgid="3465257127433353857">"មិនមានទេ"</item> <item msgid="5044688398303285224">"បិទ"</item> diff --git a/packages/SystemUI/res/values-kn/strings.xml b/packages/SystemUI/res/values-kn/strings.xml index 670ba043fee1..8ad74af35ede 100644 --- a/packages/SystemUI/res/values-kn/strings.xml +++ b/packages/SystemUI/res/values-kn/strings.xml @@ -388,6 +388,9 @@ <string name="performance" msgid="6552785217174378320">"ಪರ್ಫಾರ್ಮೆನ್ಸ್"</string> <string name="user_interface" msgid="3712869377953950887">"ಬಳಕೆದಾರ ಇಂಟರ್ಫೇಸ್"</string> <string name="thermal" msgid="6758074791325414831">"ಥರ್ಮಲ್"</string> + <string name="custom" msgid="3337456985275158299">"ಕಸ್ಟಮ್"</string> + <string name="custom_trace_settings_dialog_title" msgid="2608570500144830554">"ಕಸ್ಟಮ್ ಜಾಡಿನ ಸೆಟ್ಟಿಂಗ್ಗಳು"</string> + <string name="restore_default" msgid="5259420807486239755">"ಡೀಫಾಲ್ಟ್ ಅನ್ನು ಮರುಸ್ಥಾಪಿಸಿ"</string> <string name="quick_settings_onehanded_label" msgid="2416537930246274991">"ಒಂದು ಕೈ ಮೋಡ್"</string> <string name="quick_settings_hearing_devices_label" msgid="7277170419679404129">"ಶ್ರವಣ ಸಾಧನಗಳು"</string> <string name="quick_settings_hearing_devices_connected" msgid="6519069502397037781">"ಸಕ್ರಿಯವಾಗಿದೆ"</string> @@ -431,6 +434,12 @@ <string name="zen_modes_dialog_settings" msgid="2310248023728936697">"ಸೆಟ್ಟಿಂಗ್ಗಳು"</string> <string name="zen_mode_on" msgid="9085304934016242591">"ಆನ್ ಆಗಿದೆ"</string> <string name="zen_mode_off" msgid="1736604456618147306">"ಆಫ್ ಆಗಿದೆ"</string> + <!-- no translation found for zen_mode_set_up (7457957033034460064) --> + <skip /> + <!-- no translation found for zen_mode_no_manual_invocation (1769975741344633672) --> + <skip /> + <!-- no translation found for zen_mode_active_modes (1625850411578488856) --> + <skip /> <string name="zen_priority_introduction" msgid="3159291973383796646">"ಅಲಾರಾಂಗಳು, ಜ್ಞಾಪನೆಗಳು, ಈವೆಂಟ್ಗಳು ಹಾಗೂ ನೀವು ಸೂಚಿಸಿರುವ ಕರೆದಾರರನ್ನು ಹೊರತುಪಡಿಸಿ ಬೇರಾವುದೇ ಸದ್ದುಗಳು ಅಥವಾ ವೈಬ್ರೇಶನ್ಗಳು ನಿಮಗೆ ತೊಂದರೆ ನೀಡುವುದಿಲ್ಲ. ಹಾಗಿದ್ದರೂ, ನೀವು ಪ್ಲೇ ಮಾಡುವ ಸಂಗೀತ, ವೀಡಿಯೊಗಳು ಮತ್ತು ಆಟಗಳ ಆಡಿಯೊವನ್ನು ನೀವು ಕೇಳಿಸಿಕೊಳ್ಳುತ್ತೀರಿ."</string> <string name="zen_alarms_introduction" msgid="3987266042682300470">"ಅಲಾರಾಂಗಳನ್ನು ಹೊರತುಪಡಿಸಿ, ಬೇರಾವುದೇ ಸದ್ದುಗಳು ಅಥವಾ ವೈಬ್ರೇಶನ್ಗಳು ನಿಮಗೆ ತೊಂದರೆ ನೀಡುವುದಿಲ್ಲ. ಹಾಗಿದ್ದರೂ, ನೀವು ಪ್ಲೇ ಮಾಡುವ ಸಂಗೀತ, ವೀಡಿಯೊಗಳು ಮತ್ತು ಆಟಗಳ ಆಡಿಯೊವನ್ನು ಕೇಳಿಸಿಕೊಳ್ಳುತ್ತೀರಿ."</string> <string name="zen_priority_customize_button" msgid="4119213187257195047">"ಕಸ್ಟಮೈಸ್ ಮಾಡು"</string> @@ -469,6 +478,8 @@ <string name="keyguard_indication_charging_time_slowly" msgid="301936949731705417">"<xliff:g id="PERCENTAGE">%2$s</xliff:g> • ನಿಧಾನವಾಗಿ ಚಾರ್ಜ್ ಆಗುತ್ತಿದೆ • <xliff:g id="CHARGING_TIME_LEFT">%1$s</xliff:g> ಸಮಯದಲ್ಲಿ ಪೂರ್ಣಗೊಳ್ಳುತ್ತದೆ"</string> <string name="keyguard_indication_charging_time_dock" msgid="3149328898931741271">"<xliff:g id="PERCENTAGE">%2$s</xliff:g> • ಚಾರ್ಜ್ ಆಗುತ್ತಿದೆ • <xliff:g id="CHARGING_TIME_LEFT">%1$s</xliff:g> ದಲ್ಲಿ ಪೂರ್ಣಗೊಳ್ಳುತ್ತದೆ"</string> <string name="accessibility_action_open_communal_hub" msgid="3081702792413787849">"ಲಾಕ್ ಸ್ಕ್ರೀನ್ನಲ್ಲಿ ವಿಜೆಟ್ಗಳು"</string> + <!-- no translation found for accessibility_announcement_communal_widget_added (6911593106099328271) --> + <skip /> <string name="communal_tutorial_indicator_text" msgid="4503010353591430123">"ಸಮುದಾಯದ ಟ್ಯುಟೋರಿಯಲ್ ಅನ್ನು ಪ್ರಾರಂಭಿಸಲು ಎಡಕ್ಕೆ ಸ್ವೈಪ್ ಮಾಡಿ"</string> <string name="cta_tile_button_to_open_widget_editor" msgid="3871562362382963878">"ಕಸ್ಟಮೈಸ್ ಮಾಡಿ"</string> <string name="cta_tile_button_to_dismiss" msgid="3377597875997861754">"ವಜಾಗೊಳಿಸಿ"</string> @@ -554,10 +565,8 @@ <string name="media_projection_action_text" msgid="3634906766918186440">"ಈಗ ಪ್ರಾರಂಭಿಸಿ"</string> <string name="empty_shade_text" msgid="8935967157319717412">"ಯಾವುದೇ ಅಧಿಸೂಚನೆಗಳಿಲ್ಲ"</string> <string name="no_unseen_notif_text" msgid="395512586119868682">"ಯಾವುದೇ ಹೊಸ ಅಧಿಸೂಚನೆಗಳಿಲ್ಲ"</string> - <!-- no translation found for adaptive_notification_edu_hun_title (7790738150177329960) --> - <skip /> - <!-- no translation found for adaptive_notification_edu_hun_text (7743367744129536610) --> - <skip /> + <string name="adaptive_notification_edu_hun_title" msgid="7790738150177329960">"ನೋಟಿಫಿಕೇಶನ್ ಕೂಲ್ಡೌನ್ ಆನ್ ಆಗಿದೆ"</string> + <string name="adaptive_notification_edu_hun_text" msgid="7743367744129536610">"ನೀವು ಏಕಕಾಲದಲ್ಲಿ ತೀರಾ ಹೆಚ್ಚು ನೋಟಿಫಿಕೇಶನ್ಗಳನ್ನು ಪಡೆದಾಗ 2 ನಿಮಿಷಗಳವರೆಗೆ ನಿಮ್ಮ ಸಾಧನದ ವಾಲ್ಯೂಮ್ ಮತ್ತು ಅಲರ್ಟ್ಗಳನ್ನು ಸ್ವಯಂಚಾಲಿತವಾಗಿ ಕಡಿಮೆ ಮಾಡಲಾಗುತ್ತದೆ."</string> <string name="go_to_adaptive_notification_settings" msgid="2423690125178298479">"ಆಫ್ ಮಾಡಿ"</string> <string name="unlock_to_see_notif_text" msgid="7439033907167561227">"ಹಳೆಯ ಅಧಿಸೂಚನೆಗಳನ್ನು ನೋಡಲು ಅನ್ಲಾಕ್ ಮಾಡಿ"</string> <string name="quick_settings_disclosure_parental_controls" msgid="2114102871438223600">"ಈ ಸಾಧನವನ್ನು ನಿಮ್ಮ ಪೋಷಕರು ನಿರ್ವಹಿಸುತ್ತಿದ್ದಾರೆ"</string> @@ -1223,7 +1232,6 @@ <string name="accessibility_fingerprint_bouncer" msgid="7189102492498735519">"ದೃಢೀಕರಣದ ಅವಶ್ಯಕತೆಯಿದೆ. ದೃಢೀಕರಿಸಲು ಫಿಂಗರ್ಪ್ರಿಂಟ್ ಸೆನ್ಸರ್ ಅನ್ನು ಸ್ಪರ್ಶಿಸಿ."</string> <string name="ongoing_phone_call_content_description" msgid="5332334388483099947">"ಚಾಲ್ತಿಯಲ್ಲಿರುವ ಫೋನ್ ಕರೆ"</string> <string name="mobile_data_settings_title" msgid="3955246641380064901">"ಮೊಬೈಲ್ ಡೇಟಾ"</string> - <string name="preference_summary_default_combination" msgid="8453246369903749670">"<xliff:g id="STATE">%1$s</xliff:g> / <xliff:g id="NETWORKMODE">%2$s</xliff:g>"</string> <string name="mobile_data_connection_active" msgid="944490013299018227">"ಕನೆಕ್ಟ್ ಆಗಿದೆ"</string> <string name="mobile_data_temp_connection_active" msgid="4590222725908806824">"ತಾತ್ಕಾಲಿಕವಾಗಿ ಕನೆಕ್ಟ್ ಮಾಡಲಾಗಿದೆ"</string> <string name="mobile_data_poor_connection" msgid="819617772268371434">"ಕಳಪೆ ಸಂಪರ್ಕ"</string> @@ -1377,7 +1385,10 @@ <string name="touchpad_tutorial_done_button" msgid="176168488821755503">"ಮುಗಿದಿದೆ"</string> <string name="touchpad_tutorial_gesture_done" msgid="4784438360736821255">"ಭೇಷ್!"</string> <string name="touchpad_back_gesture_action_title" msgid="7199067250654332735">"ಹಿಂತಿರುಗಿ"</string> - <string name="touchpad_back_gesture_guidance" msgid="4222430588599527272">"ಹಿಂತಿರುಗಲು, ಟಚ್ಪ್ಯಾಡ್ನಲ್ಲಿ ಎಲ್ಲಿಯಾದರೂ ಮೂರು ಬೆರಳುಗಳನ್ನು ಬಳಸಿ ಎಡ ಅಥವಾ ಬಲಕ್ಕೆ ಸ್ವೈಪ್ ಮಾಡಿ."</string> + <!-- no translation found for touchpad_back_gesture_guidance (6263750214998421587) --> + <skip /> + <!-- no translation found for touchpad_back_gesture_finished (5353616006999726249) --> + <skip /> <string name="touchpad_back_gesture_animation_content_description" msgid="2646107450922379918">"ಮೂರು ಬೆರಳುಗಳು ಬಲಕ್ಕೆ ಮತ್ತು ಎಡಕ್ಕೆ ಚಲಿಸುತ್ತಿರುವುದನ್ನು ತೋರಿಸುತ್ತಿರುವ ಟಚ್ಪ್ಯಾಡ್"</string> <string name="touchpad_back_gesture_screen_animation_content_description" msgid="4036267494237748710">"ಬ್ಯಾಕ್ ಗೆಸ್ಚರ್ಗೆ ಸಂಬಂಧಿಸಿದ ಆ್ಯನಿಮೇಶನ್ ಅನ್ನು ತೋರಿಸುತ್ತಿರುವ ಸಾಧನದ ಸ್ಕ್ರೀನ್"</string> <string name="keyboard_backlight_dialog_title" msgid="8273102932345564724">"ಕೀಬೋರ್ಡ್ ಬ್ಯಾಕ್ಲೈಟ್"</string> diff --git a/packages/SystemUI/res/values-kn/tiles_states_strings.xml b/packages/SystemUI/res/values-kn/tiles_states_strings.xml index b2a75231d589..c7cb2b16a2f3 100644 --- a/packages/SystemUI/res/values-kn/tiles_states_strings.xml +++ b/packages/SystemUI/res/values-kn/tiles_states_strings.xml @@ -56,11 +56,6 @@ <item msgid="5376619709702103243">"ಆಫ್"</item> <item msgid="4875147066469902392">"ಆನ್"</item> </string-array> - <string-array name="tile_states_modes"> - <item msgid="7764936419245199023">"ಲಭ್ಯವಿಲ್ಲ"</item> - <item msgid="2004750556637773692">"ಆಫ್ ಆಗಿದೆ"</item> - <item msgid="8968530753931637871">"ಆನ್ ಆಗಿದೆ"</item> - </string-array> <string-array name="tile_states_flashlight"> <item msgid="3465257127433353857">"ಲಭ್ಯವಿಲ್ಲ"</item> <item msgid="5044688398303285224">"ಆಫ್"</item> diff --git a/packages/SystemUI/res/values-ko/strings.xml b/packages/SystemUI/res/values-ko/strings.xml index 32d4cc51d162..b904fa8023b7 100644 --- a/packages/SystemUI/res/values-ko/strings.xml +++ b/packages/SystemUI/res/values-ko/strings.xml @@ -388,6 +388,9 @@ <string name="performance" msgid="6552785217174378320">"성능"</string> <string name="user_interface" msgid="3712869377953950887">"사용자 인터페이스"</string> <string name="thermal" msgid="6758074791325414831">"열화상"</string> + <string name="custom" msgid="3337456985275158299">"맞춤"</string> + <string name="custom_trace_settings_dialog_title" msgid="2608570500144830554">"맞춤 트레이스 설정"</string> + <string name="restore_default" msgid="5259420807486239755">"기본값 복원"</string> <string name="quick_settings_onehanded_label" msgid="2416537930246274991">"한 손 사용 모드"</string> <string name="quick_settings_hearing_devices_label" msgid="7277170419679404129">"청각 보조 기기"</string> <string name="quick_settings_hearing_devices_connected" msgid="6519069502397037781">"활성"</string> @@ -429,9 +432,13 @@ <string name="zen_modes_dialog_title" msgid="4159138230418567383">"우선순위 모드"</string> <string name="zen_modes_dialog_done" msgid="6654130880256438950">"완료"</string> <string name="zen_modes_dialog_settings" msgid="2310248023728936697">"설정"</string> - <!-- no translation found for zen_mode_on (9085304934016242591) --> + <string name="zen_mode_on" msgid="9085304934016242591">"사용"</string> + <string name="zen_mode_off" msgid="1736604456618147306">"사용 안함"</string> + <!-- no translation found for zen_mode_set_up (7457957033034460064) --> <skip /> - <!-- no translation found for zen_mode_off (1736604456618147306) --> + <!-- no translation found for zen_mode_no_manual_invocation (1769975741344633672) --> + <skip /> + <!-- no translation found for zen_mode_active_modes (1625850411578488856) --> <skip /> <string name="zen_priority_introduction" msgid="3159291973383796646">"알람, 알림, 일정 및 지정한 발신자로부터 받은 전화를 제외한 소리와 진동을 끕니다. 음악, 동영상, 게임 등 재생하도록 선택한 소리는 정상적으로 들립니다."</string> <string name="zen_alarms_introduction" msgid="3987266042682300470">"알람을 제외한 소리와 진동을 끕니다. 음악, 동영상, 게임 등 재생하도록 선택한 소리는 정상적으로 들립니다."</string> @@ -471,6 +478,8 @@ <string name="keyguard_indication_charging_time_slowly" msgid="301936949731705417">"<xliff:g id="PERCENTAGE">%2$s</xliff:g> • 저속 충전 중 • <xliff:g id="CHARGING_TIME_LEFT">%1$s</xliff:g> 후 충전 완료"</string> <string name="keyguard_indication_charging_time_dock" msgid="3149328898931741271">"<xliff:g id="PERCENTAGE">%2$s</xliff:g> • 충전 중 • <xliff:g id="CHARGING_TIME_LEFT">%1$s</xliff:g> 후 충전 완료"</string> <string name="accessibility_action_open_communal_hub" msgid="3081702792413787849">"잠금 화면의 위젯"</string> + <!-- no translation found for accessibility_announcement_communal_widget_added (6911593106099328271) --> + <skip /> <string name="communal_tutorial_indicator_text" msgid="4503010353591430123">"공동 튜토리얼을 시작하려면 왼쪽으로 스와이프하세요"</string> <string name="cta_tile_button_to_open_widget_editor" msgid="3871562362382963878">"맞춤설정"</string> <string name="cta_tile_button_to_dismiss" msgid="3377597875997861754">"닫기"</string> @@ -499,8 +508,7 @@ <string name="accessibility_action_label_place_widget" msgid="1914197458644168978">"선택한 위젯 배치"</string> <string name="communal_widget_picker_title" msgid="1953369090475731663">"잠금 화면 위젯"</string> <string name="communal_widget_picker_description" msgid="490515450110487871">"태블릿이 잠겨 있어도 누구나 잠금 화면에서 위젯을 볼 수 있습니다."</string> - <!-- no translation found for accessibility_action_label_unselect_widget (1041811747619468698) --> - <skip /> + <string name="accessibility_action_label_unselect_widget" msgid="1041811747619468698">"위젯 선택 해제"</string> <string name="communal_widgets_disclaimer_title" msgid="1150954395585308868">"잠금 화면 위젯"</string> <string name="communal_widgets_disclaimer_text" msgid="1423545475160506349">"위젯을 사용하여 앱을 열려면 본인 인증을 해야 합니다. 또한 태블릿이 잠겨 있더라도 누구나 볼 수 있다는 점을 유의해야 합니다. 일부 위젯은 잠금 화면에 적합하지 않고 여기에 추가하기에 안전하지 않을 수 있습니다."</string> <string name="communal_widgets_disclaimer_button" msgid="4423059765740780753">"확인"</string> @@ -557,10 +565,8 @@ <string name="media_projection_action_text" msgid="3634906766918186440">"시작하기"</string> <string name="empty_shade_text" msgid="8935967157319717412">"알림 없음"</string> <string name="no_unseen_notif_text" msgid="395512586119868682">"새로운 알림 없음"</string> - <!-- no translation found for adaptive_notification_edu_hun_title (7790738150177329960) --> - <skip /> - <!-- no translation found for adaptive_notification_edu_hun_text (7743367744129536610) --> - <skip /> + <string name="adaptive_notification_edu_hun_title" msgid="7790738150177329960">"알림 쿨다운 사용 중"</string> + <string name="adaptive_notification_edu_hun_text" msgid="7743367744129536610">"한 번에 너무 많은 알림을 받으면 최대 2분간 자동으로 기기 볼륨이 줄어들고 알림이 최소화됩니다."</string> <string name="go_to_adaptive_notification_settings" msgid="2423690125178298479">"사용 중지"</string> <string name="unlock_to_see_notif_text" msgid="7439033907167561227">"잠금 해제하여 이전 알림 보기"</string> <string name="quick_settings_disclosure_parental_controls" msgid="2114102871438223600">"부모님이 관리하는 기기입니다."</string> @@ -1226,7 +1232,6 @@ <string name="accessibility_fingerprint_bouncer" msgid="7189102492498735519">"인증이 필요합니다. 지문 센서를 터치하여 인증하세요."</string> <string name="ongoing_phone_call_content_description" msgid="5332334388483099947">"진행 중인 전화 통화"</string> <string name="mobile_data_settings_title" msgid="3955246641380064901">"모바일 데이터"</string> - <string name="preference_summary_default_combination" msgid="8453246369903749670">"<xliff:g id="STATE">%1$s</xliff:g>/<xliff:g id="NETWORKMODE">%2$s</xliff:g>"</string> <string name="mobile_data_connection_active" msgid="944490013299018227">"연결됨"</string> <string name="mobile_data_temp_connection_active" msgid="4590222725908806824">"일시적으로 연결됨"</string> <string name="mobile_data_poor_connection" msgid="819617772268371434">"연결 상태 나쁨"</string> @@ -1380,7 +1385,10 @@ <string name="touchpad_tutorial_done_button" msgid="176168488821755503">"완료"</string> <string name="touchpad_tutorial_gesture_done" msgid="4784438360736821255">"아주 좋습니다."</string> <string name="touchpad_back_gesture_action_title" msgid="7199067250654332735">"뒤로"</string> - <string name="touchpad_back_gesture_guidance" msgid="4222430588599527272">"돌아가려면 세 손가락을 사용해 터치패드의 아무 곳이나 왼쪽 또는 오른쪽으로 스와이프합니다."</string> + <!-- no translation found for touchpad_back_gesture_guidance (6263750214998421587) --> + <skip /> + <!-- no translation found for touchpad_back_gesture_finished (5353616006999726249) --> + <skip /> <string name="touchpad_back_gesture_animation_content_description" msgid="2646107450922379918">"터치패드에서 세 손가락을 좌우로 움직이는 모습"</string> <string name="touchpad_back_gesture_screen_animation_content_description" msgid="4036267494237748710">"뒤로 동작 애니메이션을 보여 주는 기기 화면"</string> <string name="keyboard_backlight_dialog_title" msgid="8273102932345564724">"키보드 백라이트"</string> @@ -1388,28 +1396,16 @@ <string name="home_controls_dream_label" msgid="6567105701292324257">"홈 컨트롤"</string> <string name="home_controls_dream_description" msgid="4644150952104035789">"화면 보호기로 홈 컨트롤에 빠르게 액세스하기"</string> <string name="volume_undo_action" msgid="5815519725211877114">"실행취소"</string> - <!-- no translation found for back_edu_toast_content (4530314597378982956) --> - <skip /> - <!-- no translation found for home_edu_toast_content (3381071147871955415) --> - <skip /> - <!-- no translation found for overview_edu_toast_content (5797030644017804518) --> - <skip /> - <!-- no translation found for all_apps_edu_toast_content (8807496014667211562) --> - <skip /> - <!-- no translation found for back_edu_notification_title (5624780717751357278) --> - <skip /> - <!-- no translation found for back_edu_notification_content (2497557451540954068) --> - <skip /> - <!-- no translation found for home_edu_notification_title (6097902076909654045) --> - <skip /> - <!-- no translation found for home_edu_notification_content (6631697734535766588) --> - <skip /> - <!-- no translation found for overview_edu_notification_title (1265824157319562406) --> - <skip /> - <!-- no translation found for overview_edu_notification_content (3578204677648432500) --> - <skip /> - <!-- no translation found for all_apps_edu_notification_title (372262997265569063) --> - <skip /> - <!-- no translation found for all_apps_edu_notification_content (3255070575694025585) --> - <skip /> + <string name="back_edu_toast_content" msgid="4530314597378982956">"돌아가려면 터치패드에서 세 손가락을 사용해 왼쪽 또는 오른쪽으로 스와이프하세요"</string> + <string name="home_edu_toast_content" msgid="3381071147871955415">"홈으로 이동하려면 터치패드에서 세 손가락을 사용해 위로 스와이프합니다"</string> + <string name="overview_edu_toast_content" msgid="5797030644017804518">"최근 앱을 보려면 터치패드에서 세 손가락으로 위로 스와이프한 후 잠시 기다리세요"</string> + <string name="all_apps_edu_toast_content" msgid="8807496014667211562">"모든 앱을 보려면 키보드의 작업 키를 누르세요"</string> + <string name="back_edu_notification_title" msgid="5624780717751357278">"터치패드를 사용하여 돌아가기"</string> + <string name="back_edu_notification_content" msgid="2497557451540954068">"세 손가락을 사용해 왼쪽 또는 오른쪽으로 스와이프하세요. 더 많은 동작을 알아보려면 탭하세요."</string> + <string name="home_edu_notification_title" msgid="6097902076909654045">"터치패드를 사용하여 홈으로 이동"</string> + <string name="home_edu_notification_content" msgid="6631697734535766588">"세 손가락을 사용해 위로 스와이프하세요. 더 많은 동작을 알아보려면 탭하세요."</string> + <string name="overview_edu_notification_title" msgid="1265824157319562406">"터치패드를 사용하여 최근 앱 보기"</string> + <string name="overview_edu_notification_content" msgid="3578204677648432500">"세 손가락을 사용해 위로 스와이프한 다음 잠시 기다리세요. 더 많은 동작을 알아보려면 탭하세요."</string> + <string name="all_apps_edu_notification_title" msgid="372262997265569063">"키보드를 사용하여 모든 앱 보기"</string> + <string name="all_apps_edu_notification_content" msgid="3255070575694025585">"언제든지 작업 키를 누릅니다. 더 많은 동작을 알아보려면 탭하세요."</string> </resources> diff --git a/packages/SystemUI/res/values-ko/tiles_states_strings.xml b/packages/SystemUI/res/values-ko/tiles_states_strings.xml index 963ecc7c7668..bc4740dbc23a 100644 --- a/packages/SystemUI/res/values-ko/tiles_states_strings.xml +++ b/packages/SystemUI/res/values-ko/tiles_states_strings.xml @@ -56,11 +56,6 @@ <item msgid="5376619709702103243">"꺼짐"</item> <item msgid="4875147066469902392">"켜짐"</item> </string-array> - <string-array name="tile_states_modes"> - <item msgid="7764936419245199023">"사용 불가"</item> - <item msgid="2004750556637773692">"사용 안 함"</item> - <item msgid="8968530753931637871">"사용"</item> - </string-array> <string-array name="tile_states_flashlight"> <item msgid="3465257127433353857">"이용 불가"</item> <item msgid="5044688398303285224">"꺼짐"</item> diff --git a/packages/SystemUI/res/values-ky/strings.xml b/packages/SystemUI/res/values-ky/strings.xml index b96732eadb1b..7cea137cb77c 100644 --- a/packages/SystemUI/res/values-ky/strings.xml +++ b/packages/SystemUI/res/values-ky/strings.xml @@ -388,6 +388,9 @@ <string name="performance" msgid="6552785217174378320">"Иштин майнаптуулугу"</string> <string name="user_interface" msgid="3712869377953950887">"Колдонуучунун интерфейси"</string> <string name="thermal" msgid="6758074791325414831">"Жылуулук"</string> + <string name="custom" msgid="3337456985275158299">"Жеке"</string> + <string name="custom_trace_settings_dialog_title" msgid="2608570500144830554">"Көз салуунун жеке параметрлери"</string> + <string name="restore_default" msgid="5259420807486239755">"Демейки параметрди калыбына келтирүү"</string> <string name="quick_settings_onehanded_label" msgid="2416537930246274991">"Бир кол режими"</string> <string name="quick_settings_hearing_devices_label" msgid="7277170419679404129">"Угуу аппараттары"</string> <string name="quick_settings_hearing_devices_connected" msgid="6519069502397037781">"Иштеп жатат"</string> @@ -429,9 +432,13 @@ <string name="zen_modes_dialog_title" msgid="4159138230418567383">"Маанилүүлүк режимдери"</string> <string name="zen_modes_dialog_done" msgid="6654130880256438950">"Бүттү"</string> <string name="zen_modes_dialog_settings" msgid="2310248023728936697">"Параметрлер"</string> - <!-- no translation found for zen_mode_on (9085304934016242591) --> + <string name="zen_mode_on" msgid="9085304934016242591">"Күйүк"</string> + <string name="zen_mode_off" msgid="1736604456618147306">"Өчүк"</string> + <!-- no translation found for zen_mode_set_up (7457957033034460064) --> <skip /> - <!-- no translation found for zen_mode_off (1736604456618147306) --> + <!-- no translation found for zen_mode_no_manual_invocation (1769975741344633672) --> + <skip /> + <!-- no translation found for zen_mode_active_modes (1625850411578488856) --> <skip /> <string name="zen_priority_introduction" msgid="3159291973383796646">"Ойготкучтардан, эскертүүлөрдөн, жылнаамадагы иш-чараларды эстеткичтерден жана белгиленген байланыштардын чалууларынан тышкары башка үндөр жана дирилдөөлөр тынчыңызды албайт. Бирок ойнотулуп жаткан музыканы, видеолорду жана оюндарды мурдагыдай эле уга бересиз."</string> <string name="zen_alarms_introduction" msgid="3987266042682300470">"Ойготкучтардан башка үндөр жана дирилдөөлөр тынчыңызды албайт. Бирок ойнотулуп жаткан музыканы, видеолорду жана оюндарды мурдагыдай эле уга бересиз."</string> @@ -471,6 +478,8 @@ <string name="keyguard_indication_charging_time_slowly" msgid="301936949731705417">"<xliff:g id="PERCENTAGE">%2$s</xliff:g> • Жай кубатталууда • Толгонго чейин <xliff:g id="CHARGING_TIME_LEFT">%1$s</xliff:g> калды"</string> <string name="keyguard_indication_charging_time_dock" msgid="3149328898931741271">"<xliff:g id="PERCENTAGE">%2$s</xliff:g> • Кубатталууда • Толгонго чейин <xliff:g id="CHARGING_TIME_LEFT">%1$s</xliff:g> калды"</string> <string name="accessibility_action_open_communal_hub" msgid="3081702792413787849">"Кулпуланган экрандагы виджеттер"</string> + <!-- no translation found for accessibility_announcement_communal_widget_added (6911593106099328271) --> + <skip /> <string name="communal_tutorial_indicator_text" msgid="4503010353591430123">"Жалпы үйрөткүчтү иштетүү үчүн солго сүрүңүз"</string> <string name="cta_tile_button_to_open_widget_editor" msgid="3871562362382963878">"Ыңгайлаштыруу"</string> <string name="cta_tile_button_to_dismiss" msgid="3377597875997861754">"Жабуу"</string> @@ -499,8 +508,7 @@ <string name="accessibility_action_label_place_widget" msgid="1914197458644168978">"тандалган виджетти жайгаштыруу"</string> <string name="communal_widget_picker_title" msgid="1953369090475731663">"Кулпуланган экрандагы виджеттер"</string> <string name="communal_widget_picker_description" msgid="490515450110487871">"Планшетиңиз кулпуланган болсо да, кулпуланган экраныңыздан виджеттерди бардыгы көрө алат."</string> - <!-- no translation found for accessibility_action_label_unselect_widget (1041811747619468698) --> - <skip /> + <string name="accessibility_action_label_unselect_widget" msgid="1041811747619468698">"виджетти тандоодон чыгаруу"</string> <string name="communal_widgets_disclaimer_title" msgid="1150954395585308868">"Кулпуланган экрандагы виджеттер"</string> <string name="communal_widgets_disclaimer_text" msgid="1423545475160506349">"Колдонмону виджет аркылуу ачуу үчүн бул сиз экениңизди ырасташыңыз керек. Аларды планшетиңиз кулпуланып турса да, баары көрө аларын эске алыңыз. Айрым виджеттер кулпуланган экранда колдонууга арналган эмес жана аларды бул жерге кошуу кооптуу болушу мүмкүн."</string> <string name="communal_widgets_disclaimer_button" msgid="4423059765740780753">"Түшүндүм"</string> @@ -557,10 +565,8 @@ <string name="media_projection_action_text" msgid="3634906766918186440">"Азыр баштоо"</string> <string name="empty_shade_text" msgid="8935967157319717412">"Билдирме жок"</string> <string name="no_unseen_notif_text" msgid="395512586119868682">"Жаңы билдирмелер жок"</string> - <!-- no translation found for adaptive_notification_edu_hun_title (7790738150177329960) --> - <skip /> - <!-- no translation found for adaptive_notification_edu_hun_text (7743367744129536610) --> - <skip /> + <string name="adaptive_notification_edu_hun_title" msgid="7790738150177329960">"Билдирмелердин үнүн басаңдатуу күйүк"</string> + <string name="adaptive_notification_edu_hun_text" msgid="7743367744129536610">"Бир убакта өтө көп билдирмелер келгенде, түзмөктүн үнү жана эскертүүлөрдүн саны 2 мүнөткө азайтылат."</string> <string name="go_to_adaptive_notification_settings" msgid="2423690125178298479">"Өчүрүү"</string> <string name="unlock_to_see_notif_text" msgid="7439033907167561227">"Билдирмелерди көрүү үчүн кулпуну ачыңыз"</string> <string name="quick_settings_disclosure_parental_controls" msgid="2114102871438223600">"Бул түзмөктү ата-энең башкарат"</string> @@ -1226,7 +1232,6 @@ <string name="accessibility_fingerprint_bouncer" msgid="7189102492498735519">"Аныктыкты текшерүү талап кылынат. Аныктыгын текшерүү үчүн манжа изинин сенсоруна тийип коюңуз."</string> <string name="ongoing_phone_call_content_description" msgid="5332334388483099947">"Учурдагы телефон чалуу"</string> <string name="mobile_data_settings_title" msgid="3955246641380064901">"Мобилдик трафик"</string> - <string name="preference_summary_default_combination" msgid="8453246369903749670">"<xliff:g id="STATE">%1$s</xliff:g> / <xliff:g id="NETWORKMODE">%2$s</xliff:g>"</string> <string name="mobile_data_connection_active" msgid="944490013299018227">"Туташты"</string> <string name="mobile_data_temp_connection_active" msgid="4590222725908806824">"Убактылуу туташып турат"</string> <string name="mobile_data_poor_connection" msgid="819617772268371434">"Байланыш начар"</string> @@ -1380,7 +1385,10 @@ <string name="touchpad_tutorial_done_button" msgid="176168488821755503">"Бүттү"</string> <string name="touchpad_tutorial_gesture_done" msgid="4784438360736821255">"Азаматсыз!"</string> <string name="touchpad_back_gesture_action_title" msgid="7199067250654332735">"Артка кайтуу"</string> - <string name="touchpad_back_gesture_guidance" msgid="4222430588599527272">"Кайтуу үчүн сенсордук тактанын каалаган жерин үч манжаңыз менен солго же оңго сүрүңүз."</string> + <!-- no translation found for touchpad_back_gesture_guidance (6263750214998421587) --> + <skip /> + <!-- no translation found for touchpad_back_gesture_finished (5353616006999726249) --> + <skip /> <string name="touchpad_back_gesture_animation_content_description" msgid="2646107450922379918">"Үч манжанын оңго жана солго жылып жатканы көрсөтүлгөн сенсордук такта"</string> <string name="touchpad_back_gesture_screen_animation_content_description" msgid="4036267494237748710">"Артка жаңсоосунун анимациясы көрсөтүлгөн түзмөктүн экраны"</string> <string name="keyboard_backlight_dialog_title" msgid="8273102932345564724">"Баскычтоптун жарыгы"</string> @@ -1388,28 +1396,16 @@ <string name="home_controls_dream_label" msgid="6567105701292324257">"Үйдөгү түзмөктөрдү тескөө"</string> <string name="home_controls_dream_description" msgid="4644150952104035789">"Үйдөгү түзмөктөрдү көшөгөдөн ыкчам тескеңиз"</string> <string name="volume_undo_action" msgid="5815519725211877114">"Кайтаруу"</string> - <!-- no translation found for back_edu_toast_content (4530314597378982956) --> - <skip /> - <!-- no translation found for home_edu_toast_content (3381071147871955415) --> - <skip /> - <!-- no translation found for overview_edu_toast_content (5797030644017804518) --> - <skip /> - <!-- no translation found for all_apps_edu_toast_content (8807496014667211562) --> - <skip /> - <!-- no translation found for back_edu_notification_title (5624780717751357278) --> - <skip /> - <!-- no translation found for back_edu_notification_content (2497557451540954068) --> - <skip /> - <!-- no translation found for home_edu_notification_title (6097902076909654045) --> - <skip /> - <!-- no translation found for home_edu_notification_content (6631697734535766588) --> - <skip /> - <!-- no translation found for overview_edu_notification_title (1265824157319562406) --> - <skip /> - <!-- no translation found for overview_edu_notification_content (3578204677648432500) --> - <skip /> - <!-- no translation found for all_apps_edu_notification_title (372262997265569063) --> - <skip /> - <!-- no translation found for all_apps_edu_notification_content (3255070575694025585) --> - <skip /> + <string name="back_edu_toast_content" msgid="4530314597378982956">"Артка кайтуу үчүн сенсордук тактаны үч манжаңыз менен солго же оңго сүрүңүз"</string> + <string name="home_edu_toast_content" msgid="3381071147871955415">"Башкы бетке өтүү үчүн сенсордук тактаны үч манжаңыз менен өйдө сүрүңүз"</string> + <string name="overview_edu_toast_content" msgid="5797030644017804518">"Акыркы колдонмолорду көрүү үчүн сенсордук тактаны үч манжаңыз менен өйдө сүрүп, кармап туруңуз"</string> + <string name="all_apps_edu_toast_content" msgid="8807496014667211562">"Бардык колдонмолоруңузду көрүү үчүн баскычтобуңуздагы аракет баскычын басыңыз"</string> + <string name="back_edu_notification_title" msgid="5624780717751357278">"Артка кайтуу үчүн сенсордук тактаны колдонуңуз"</string> + <string name="back_edu_notification_content" msgid="2497557451540954068">"Үч манжаңыз менен солго же оңго сүрүңүз. Башка жаңсоолорду үйрөнүү үчүн таптаңыз."</string> + <string name="home_edu_notification_title" msgid="6097902076909654045">"Башкы бетке өтүү үчүн сенсордук тактаны колдонуңуз"</string> + <string name="home_edu_notification_content" msgid="6631697734535766588">"Үч манжаңыз менен өйдө сүрүңүз. Башка жаңсоолорду үйрөнүү үчүн таптаңыз."</string> + <string name="overview_edu_notification_title" msgid="1265824157319562406">"Акыркы колдонмолорду көрүү үчүн сенсордук тактаны колдонуңуз"</string> + <string name="overview_edu_notification_content" msgid="3578204677648432500">"Үч манжаңыз менен өйдө сүрүп, кармап туруңуз. Башка жаңсоолорду үйрөнүү үчүн таптаңыз."</string> + <string name="all_apps_edu_notification_title" msgid="372262997265569063">"Бардык колдонмолорду көрүү үчүн баскычтобуңузду колдонуңуз"</string> + <string name="all_apps_edu_notification_content" msgid="3255070575694025585">"Каалаганда аракет баскычын басыңыз. Башка жаңсоолорду үйрөнүү үчүн таптаңыз."</string> </resources> diff --git a/packages/SystemUI/res/values-ky/tiles_states_strings.xml b/packages/SystemUI/res/values-ky/tiles_states_strings.xml index 3ad9b64ed720..694967e3d8d6 100644 --- a/packages/SystemUI/res/values-ky/tiles_states_strings.xml +++ b/packages/SystemUI/res/values-ky/tiles_states_strings.xml @@ -56,11 +56,6 @@ <item msgid="5376619709702103243">"Өчүк"</item> <item msgid="4875147066469902392">"Күйүк"</item> </string-array> - <string-array name="tile_states_modes"> - <item msgid="7764936419245199023">"Жеткиликсиз"</item> - <item msgid="2004750556637773692">"Өчүк"</item> - <item msgid="8968530753931637871">"Күйүк"</item> - </string-array> <string-array name="tile_states_flashlight"> <item msgid="3465257127433353857">"Жеткиликсиз"</item> <item msgid="5044688398303285224">"Өчүк"</item> diff --git a/packages/SystemUI/res/values-lo/strings.xml b/packages/SystemUI/res/values-lo/strings.xml index 4f3e82e61d42..2c490ac84c9d 100644 --- a/packages/SystemUI/res/values-lo/strings.xml +++ b/packages/SystemUI/res/values-lo/strings.xml @@ -388,6 +388,9 @@ <string name="performance" msgid="6552785217174378320">"ປະສິດທິພາບ"</string> <string name="user_interface" msgid="3712869377953950887">"ສ່ວນຕິດຕໍ່ຜູ້ໃຊ້"</string> <string name="thermal" msgid="6758074791325414831">"ຄວາມຮ້ອນ"</string> + <string name="custom" msgid="3337456985275158299">"ກຳນົດເອງ"</string> + <string name="custom_trace_settings_dialog_title" msgid="2608570500144830554">"ການຕັ້ງຄ່າການຕິດຕາມແບບກຳນົດເອງ"</string> + <string name="restore_default" msgid="5259420807486239755">"ກູ້ຄືນຄ່າເລີ່ມຕົ້ນ"</string> <string name="quick_settings_onehanded_label" msgid="2416537930246274991">"ໂໝດມືດຽວ"</string> <string name="quick_settings_hearing_devices_label" msgid="7277170419679404129">"ອຸປະກອນຊ່ວຍຟັງ"</string> <string name="quick_settings_hearing_devices_connected" msgid="6519069502397037781">"ນຳໃຊ້ຢູ່"</string> @@ -431,6 +434,12 @@ <string name="zen_modes_dialog_settings" msgid="2310248023728936697">"ການຕັ້ງຄ່າ"</string> <string name="zen_mode_on" msgid="9085304934016242591">"ເປີດ"</string> <string name="zen_mode_off" msgid="1736604456618147306">"ປິດ"</string> + <!-- no translation found for zen_mode_set_up (7457957033034460064) --> + <skip /> + <!-- no translation found for zen_mode_no_manual_invocation (1769975741344633672) --> + <skip /> + <!-- no translation found for zen_mode_active_modes (1625850411578488856) --> + <skip /> <string name="zen_priority_introduction" msgid="3159291973383796646">"ທ່ານຈະບໍ່ໄດ້ຮັບການລົບກວນຈາກສຽງ ແລະ ການສັ່ນເຕືອນ, ຍົກເວັ້ນໃນເວລາໂມງປຸກດັງ, ມີການແຈ້ງເຕືອນ ຫຼື ມີສາຍໂທເຂົ້າຈາກຜູ້ໂທທີ່ທ່ານລະບຸໄວ້. ທ່ານອາດຍັງຄົງໄດ້ຍິນຫາກທ່ານເລືອກຫຼິ້ນເພງ, ວິດີໂອ ແລະ ເກມ."</string> <string name="zen_alarms_introduction" msgid="3987266042682300470">"ທ່ານຈະບໍ່ໄດ້ຮັບການລົບກວນຈາກສຽງ ແລະ ການສັ່ນເຕືອນ, ຍົກເວັ້ນໃນເວລາໂມງປຸກດັງ. ທ່ານອາດຍັງຄົງໄດ້ຍິນຫາກທ່ານເລືອກຫຼິ້ນເພງ, ວິດີໂອ ແລະ ເກມ."</string> <string name="zen_priority_customize_button" msgid="4119213187257195047">"ປັບແຕ່ງ"</string> @@ -469,6 +478,8 @@ <string name="keyguard_indication_charging_time_slowly" msgid="301936949731705417">"<xliff:g id="PERCENTAGE">%2$s</xliff:g> • ກຳລັງສາກໄຟແບບຊ້າ • ຈະເຕັມໃນອີກ <xliff:g id="CHARGING_TIME_LEFT">%1$s</xliff:g>"</string> <string name="keyguard_indication_charging_time_dock" msgid="3149328898931741271">"<xliff:g id="PERCENTAGE">%2$s</xliff:g> • ກຳລັງສາກໄຟ • ຈະເຕັມໃນອີກ <xliff:g id="CHARGING_TIME_LEFT">%1$s</xliff:g>"</string> <string name="accessibility_action_open_communal_hub" msgid="3081702792413787849">"ວິດເຈັດຢູ່ໜ້າຈໍລັອກ"</string> + <!-- no translation found for accessibility_announcement_communal_widget_added (6911593106099328271) --> + <skip /> <string name="communal_tutorial_indicator_text" msgid="4503010353591430123">"ປັດຊ້າຍເພື່ອເລີ່ມບົດແນະນຳສ່ວນກາງ"</string> <string name="cta_tile_button_to_open_widget_editor" msgid="3871562362382963878">"ປັບແຕ່ງ"</string> <string name="cta_tile_button_to_dismiss" msgid="3377597875997861754">"ປ່ອຍໄປ"</string> @@ -554,10 +565,8 @@ <string name="media_projection_action_text" msgid="3634906766918186440">"ເລີ່ມດຽວນີ້"</string> <string name="empty_shade_text" msgid="8935967157319717412">"ບໍ່ມີການແຈ້ງເຕືອນ"</string> <string name="no_unseen_notif_text" msgid="395512586119868682">"ບໍ່ມີການແຈ້ງເຕືອນໃໝ່"</string> - <!-- no translation found for adaptive_notification_edu_hun_title (7790738150177329960) --> - <skip /> - <!-- no translation found for adaptive_notification_edu_hun_text (7743367744129536610) --> - <skip /> + <string name="adaptive_notification_edu_hun_title" msgid="7790738150177329960">"ຄູດາວການແຈ້ງເຕືອນເປີດຢູ່"</string> + <string name="adaptive_notification_edu_hun_text" msgid="7743367744129536610">"ສຽງ ແລະ ແຈ້ງເຕືອນອຸປະກອນຂອງທ່ານຖືກຫຼຸດລົງໂດຍອັດຕະໂນມັດເປັນເວລາເຖິງ 2 ນາທີເມື່ອທ່ານໄດ້ຮັບການແຈ້ງເຕືອນຫຼາຍເກີນໄປໃນຄັ້ງດຽວ."</string> <string name="go_to_adaptive_notification_settings" msgid="2423690125178298479">"ປິດ"</string> <string name="unlock_to_see_notif_text" msgid="7439033907167561227">"ປົດລັອກເພື່ອເບິ່ງການແຈ້ງເຕືອນເກົ່າ"</string> <string name="quick_settings_disclosure_parental_controls" msgid="2114102871438223600">"ອຸປະກອນນີ້ແມ່ນຈັດການໂດຍພໍ່ແມ່ຂອງທ່ານ"</string> @@ -1223,7 +1232,6 @@ <string name="accessibility_fingerprint_bouncer" msgid="7189102492498735519">"ຕ້ອງພິສູດຢືນຢັນ. ແຕະໃສ່ເຊັນເຊີລາຍນິ້ວມືເພື່ອພິສູດຢືນຢັນ."</string> <string name="ongoing_phone_call_content_description" msgid="5332334388483099947">"ສາຍໂທອອກ"</string> <string name="mobile_data_settings_title" msgid="3955246641380064901">"ອິນເຕີເນັດມືຖື"</string> - <string name="preference_summary_default_combination" msgid="8453246369903749670">"<xliff:g id="STATE">%1$s</xliff:g> / <xliff:g id="NETWORKMODE">%2$s</xliff:g>"</string> <string name="mobile_data_connection_active" msgid="944490013299018227">"ເຊື່ອມຕໍ່ແລ້ວ"</string> <string name="mobile_data_temp_connection_active" msgid="4590222725908806824">"ເຊື່ອມຕໍ່ແລ້ວຊົ່ວຄາວ"</string> <string name="mobile_data_poor_connection" msgid="819617772268371434">"ສັນຍານເຊື່ອມຕໍ່ຊ້າ"</string> @@ -1377,7 +1385,10 @@ <string name="touchpad_tutorial_done_button" msgid="176168488821755503">"ແລ້ວໆ"</string> <string name="touchpad_tutorial_gesture_done" msgid="4784438360736821255">"ດີຫຼາຍ!"</string> <string name="touchpad_back_gesture_action_title" msgid="7199067250654332735">"ກັບຄືນ"</string> - <string name="touchpad_back_gesture_guidance" msgid="4222430588599527272">"ເພື່ອກັບຄືນ, ໃຫ້ໃຊ້ 3 ນິ້ວປັດຊ້າຍ ຫຼື ຂວາບ່ອນໃດກໍໄດ້ເທິງແຜ່ນສໍາຜັດ."</string> + <!-- no translation found for touchpad_back_gesture_guidance (6263750214998421587) --> + <skip /> + <!-- no translation found for touchpad_back_gesture_finished (5353616006999726249) --> + <skip /> <string name="touchpad_back_gesture_animation_content_description" msgid="2646107450922379918">"ແຜ່ນສໍາຜັດສະແດງພາບ 3 ນິ້ວເລື່ອນໄປທາງຂວາ ແລະ ຊ້າຍ"</string> <string name="touchpad_back_gesture_screen_animation_content_description" msgid="4036267494237748710">"ໜ້າຈໍອຸປະກອນສະແດງພາບເຄື່ອນໄຫວຂອງທ່າທາງກັບຄືນ"</string> <string name="keyboard_backlight_dialog_title" msgid="8273102932345564724">"ໄຟປຸ່ມແປ້ນພິມ"</string> diff --git a/packages/SystemUI/res/values-lo/tiles_states_strings.xml b/packages/SystemUI/res/values-lo/tiles_states_strings.xml index f42e5ce91c88..9386e00af195 100644 --- a/packages/SystemUI/res/values-lo/tiles_states_strings.xml +++ b/packages/SystemUI/res/values-lo/tiles_states_strings.xml @@ -56,11 +56,6 @@ <item msgid="5376619709702103243">"ປິດ"</item> <item msgid="4875147066469902392">"ເປີດ"</item> </string-array> - <string-array name="tile_states_modes"> - <item msgid="7764936419245199023">"ບໍ່ພ້ອມນຳໃຊ້"</item> - <item msgid="2004750556637773692">"ປິດ"</item> - <item msgid="8968530753931637871">"ເປີດ"</item> - </string-array> <string-array name="tile_states_flashlight"> <item msgid="3465257127433353857">"ບໍ່ສາມາດໃຊ້ໄດ້"</item> <item msgid="5044688398303285224">"ປິດ"</item> diff --git a/packages/SystemUI/res/values-lt/strings.xml b/packages/SystemUI/res/values-lt/strings.xml index 2d48ccfb920b..6b97dc996498 100644 --- a/packages/SystemUI/res/values-lt/strings.xml +++ b/packages/SystemUI/res/values-lt/strings.xml @@ -388,6 +388,9 @@ <string name="performance" msgid="6552785217174378320">"Našumas"</string> <string name="user_interface" msgid="3712869377953950887">"Naudotojo sąsaja"</string> <string name="thermal" msgid="6758074791325414831">"Šiluminis"</string> + <string name="custom" msgid="3337456985275158299">"Tinkinta"</string> + <string name="custom_trace_settings_dialog_title" msgid="2608570500144830554">"Tinkinti pėdsako nustatymai"</string> + <string name="restore_default" msgid="5259420807486239755">"Atkurti numatytuosius nustatymus"</string> <string name="quick_settings_onehanded_label" msgid="2416537930246274991">"Vienos rankos režimas"</string> <string name="quick_settings_hearing_devices_label" msgid="7277170419679404129">"Klausos įrenginiai"</string> <string name="quick_settings_hearing_devices_connected" msgid="6519069502397037781">"Aktyvus"</string> @@ -431,6 +434,12 @@ <string name="zen_modes_dialog_settings" msgid="2310248023728936697">"Nustatymai"</string> <string name="zen_mode_on" msgid="9085304934016242591">"Įjungta"</string> <string name="zen_mode_off" msgid="1736604456618147306">"Išjungta"</string> + <!-- no translation found for zen_mode_set_up (7457957033034460064) --> + <skip /> + <!-- no translation found for zen_mode_no_manual_invocation (1769975741344633672) --> + <skip /> + <!-- no translation found for zen_mode_active_modes (1625850411578488856) --> + <skip /> <string name="zen_priority_introduction" msgid="3159291973383796646">"Jūsų netrikdys garsai ir vibravimas, išskyrus nurodytų signalų, priminimų, įvykių ir skambintojų garsus. Vis tiek girdėsite viską, ką pasirinksite leisti, įskaitant muziką, vaizdo įrašus ir žaidimus."</string> <string name="zen_alarms_introduction" msgid="3987266042682300470">"Jūsų netrikdys garsai ir vibravimas, išskyrus signalus. Vis tiek girdėsite viską, ką pasirinksite leisti, įskaitant muziką, vaizdo įrašus ir žaidimus."</string> <string name="zen_priority_customize_button" msgid="4119213187257195047">"Tinkinti"</string> @@ -469,6 +478,8 @@ <string name="keyguard_indication_charging_time_slowly" msgid="301936949731705417">"<xliff:g id="PERCENTAGE">%2$s</xliff:g> • Lėtai įkraunama • <xliff:g id="CHARGING_TIME_LEFT">%1$s</xliff:g> iki visiško įkrovimo"</string> <string name="keyguard_indication_charging_time_dock" msgid="3149328898931741271">"<xliff:g id="PERCENTAGE">%2$s</xliff:g> • Įkraunama • <xliff:g id="CHARGING_TIME_LEFT">%1$s</xliff:g> iki visiško įkrovimo"</string> <string name="accessibility_action_open_communal_hub" msgid="3081702792413787849">"Valdikliai užrakinimo ekrane"</string> + <!-- no translation found for accessibility_announcement_communal_widget_added (6911593106099328271) --> + <skip /> <string name="communal_tutorial_indicator_text" msgid="4503010353591430123">"Perbraukite kairėn, paleistumėte bendruomenės mokomąją medžiagą"</string> <string name="cta_tile_button_to_open_widget_editor" msgid="3871562362382963878">"Tinkinti"</string> <string name="cta_tile_button_to_dismiss" msgid="3377597875997861754">"Atsisakyti"</string> @@ -554,10 +565,8 @@ <string name="media_projection_action_text" msgid="3634906766918186440">"Pradėti dabar"</string> <string name="empty_shade_text" msgid="8935967157319717412">"Nėra įspėjimų"</string> <string name="no_unseen_notif_text" msgid="395512586119868682">"Naujų pranešimų nėra"</string> - <!-- no translation found for adaptive_notification_edu_hun_title (7790738150177329960) --> - <skip /> - <!-- no translation found for adaptive_notification_edu_hun_text (7743367744129536610) --> - <skip /> + <string name="adaptive_notification_edu_hun_title" msgid="7790738150177329960">"Pranešimų neaktyvumo laikotarpis įjungtas"</string> + <string name="adaptive_notification_edu_hun_text" msgid="7743367744129536610">"Jūsų įrenginio garsumas ir įspėjimai automatiškai sumažinami iki dviejų minučių, kai iš karto gaunate per daug pranešimų."</string> <string name="go_to_adaptive_notification_settings" msgid="2423690125178298479">"Išjungti"</string> <string name="unlock_to_see_notif_text" msgid="7439033907167561227">"Atrakinę matykite senesnius pranešimus"</string> <string name="quick_settings_disclosure_parental_controls" msgid="2114102871438223600">"Šį įrenginį tvarko vienas iš tavo tėvų"</string> @@ -1223,7 +1232,6 @@ <string name="accessibility_fingerprint_bouncer" msgid="7189102492498735519">"Reikia nustatyti tapatybę. Nustatykite tapatybę palietę kontrolinio kodo jutiklį."</string> <string name="ongoing_phone_call_content_description" msgid="5332334388483099947">"Vykstantis telefono skambutis"</string> <string name="mobile_data_settings_title" msgid="3955246641380064901">"Mobiliojo ryšio duomenys"</string> - <string name="preference_summary_default_combination" msgid="8453246369903749670">"<xliff:g id="STATE">%1$s</xliff:g> / <xliff:g id="NETWORKMODE">%2$s</xliff:g>"</string> <string name="mobile_data_connection_active" msgid="944490013299018227">"Prisijungta"</string> <string name="mobile_data_temp_connection_active" msgid="4590222725908806824">"Laikinai prijungta"</string> <string name="mobile_data_poor_connection" msgid="819617772268371434">"Prastas ryšys"</string> @@ -1377,7 +1385,10 @@ <string name="touchpad_tutorial_done_button" msgid="176168488821755503">"Atlikta"</string> <string name="touchpad_tutorial_gesture_done" msgid="4784438360736821255">"Puiku!"</string> <string name="touchpad_back_gesture_action_title" msgid="7199067250654332735">"Grįžti"</string> - <string name="touchpad_back_gesture_guidance" msgid="4222430588599527272">"Jei norite grįžti, trimis pirštais perbraukite kairėn arba dešinėn bet kurioje jutiklinės dalies vietoje."</string> + <!-- no translation found for touchpad_back_gesture_guidance (6263750214998421587) --> + <skip /> + <!-- no translation found for touchpad_back_gesture_finished (5353616006999726249) --> + <skip /> <string name="touchpad_back_gesture_animation_content_description" msgid="2646107450922379918">"Jutiklinė dalis, kurioje rodomi trys dešinėn ir kairėn judantys pirštai"</string> <string name="touchpad_back_gesture_screen_animation_content_description" msgid="4036267494237748710">"Įrenginio ekranas, kuriame rodoma grįžimo gesto animacija"</string> <string name="keyboard_backlight_dialog_title" msgid="8273102932345564724">"Klaviatūros foninis apšvietimas"</string> diff --git a/packages/SystemUI/res/values-lt/tiles_states_strings.xml b/packages/SystemUI/res/values-lt/tiles_states_strings.xml index 90d2e8bc7eb9..c975e7e3cc80 100644 --- a/packages/SystemUI/res/values-lt/tiles_states_strings.xml +++ b/packages/SystemUI/res/values-lt/tiles_states_strings.xml @@ -56,11 +56,6 @@ <item msgid="5376619709702103243">"Išjungta"</item> <item msgid="4875147066469902392">"Įjungta"</item> </string-array> - <string-array name="tile_states_modes"> - <item msgid="7764936419245199023">"Nepasiekiama"</item> - <item msgid="2004750556637773692">"Išjungta"</item> - <item msgid="8968530753931637871">"Įjungta"</item> - </string-array> <string-array name="tile_states_flashlight"> <item msgid="3465257127433353857">"Nepasiekiama"</item> <item msgid="5044688398303285224">"Išjungta"</item> diff --git a/packages/SystemUI/res/values-lv/strings.xml b/packages/SystemUI/res/values-lv/strings.xml index c7b1c966dad1..f191a2826d96 100644 --- a/packages/SystemUI/res/values-lv/strings.xml +++ b/packages/SystemUI/res/values-lv/strings.xml @@ -388,6 +388,9 @@ <string name="performance" msgid="6552785217174378320">"Veiktspēja"</string> <string name="user_interface" msgid="3712869377953950887">"Lietotāja saskarne"</string> <string name="thermal" msgid="6758074791325414831">"Ierīces temperatūra"</string> + <string name="custom" msgid="3337456985275158299">"Pielāgots"</string> + <string name="custom_trace_settings_dialog_title" msgid="2608570500144830554">"Pielāgoti izsekošanas iestatījumi"</string> + <string name="restore_default" msgid="5259420807486239755">"Atjaunot noklusējuma vērtību"</string> <string name="quick_settings_onehanded_label" msgid="2416537930246274991">"Vienas rokas režīms"</string> <string name="quick_settings_hearing_devices_label" msgid="7277170419679404129">"Dzirdes aparāti"</string> <string name="quick_settings_hearing_devices_connected" msgid="6519069502397037781">"Aktīvs"</string> @@ -429,9 +432,13 @@ <string name="zen_modes_dialog_title" msgid="4159138230418567383">"Prioritātes režīmi"</string> <string name="zen_modes_dialog_done" msgid="6654130880256438950">"Gatavs"</string> <string name="zen_modes_dialog_settings" msgid="2310248023728936697">"Iestatījumi"</string> - <!-- no translation found for zen_mode_on (9085304934016242591) --> + <string name="zen_mode_on" msgid="9085304934016242591">"Ieslēgts"</string> + <string name="zen_mode_off" msgid="1736604456618147306">"Izslēgts"</string> + <!-- no translation found for zen_mode_set_up (7457957033034460064) --> <skip /> - <!-- no translation found for zen_mode_off (1736604456618147306) --> + <!-- no translation found for zen_mode_no_manual_invocation (1769975741344633672) --> + <skip /> + <!-- no translation found for zen_mode_active_modes (1625850411578488856) --> <skip /> <string name="zen_priority_introduction" msgid="3159291973383796646">"Jūs netraucēs skaņas un vibrācija, izņemot signālus, atgādinājumus, pasākumus un zvanītājus, ko būsiet norādījis. Jūs joprojām dzirdēsiet atskaņošanai izvēlētos vienumus, tostarp mūziku, videoklipus un spēles."</string> <string name="zen_alarms_introduction" msgid="3987266042682300470">"Jūs netraucēs skaņas un vibrācija, izņemot signālus. Jūs joprojām dzirdēsiet atskaņošanai izvēlētos vienumus, tostarp mūziku, videoklipus un spēles."</string> @@ -471,6 +478,8 @@ <string name="keyguard_indication_charging_time_slowly" msgid="301936949731705417">"<xliff:g id="PERCENTAGE">%2$s</xliff:g> • Lēnā uzlāde • Laiks līdz pilnai uzlādei: <xliff:g id="CHARGING_TIME_LEFT">%1$s</xliff:g>"</string> <string name="keyguard_indication_charging_time_dock" msgid="3149328898931741271">"<xliff:g id="PERCENTAGE">%2$s</xliff:g> • Notiek uzlāde • Laiks līdz pilnai uzlādei: <xliff:g id="CHARGING_TIME_LEFT">%1$s</xliff:g>"</string> <string name="accessibility_action_open_communal_hub" msgid="3081702792413787849">"Logrīki bloķēšanas ekrānā"</string> + <!-- no translation found for accessibility_announcement_communal_widget_added (6911593106099328271) --> + <skip /> <string name="communal_tutorial_indicator_text" msgid="4503010353591430123">"Velciet pa kreisi, lai palaistu kopienas pamācību."</string> <string name="cta_tile_button_to_open_widget_editor" msgid="3871562362382963878">"Pielāgot"</string> <string name="cta_tile_button_to_dismiss" msgid="3377597875997861754">"Nerādīt"</string> @@ -499,8 +508,7 @@ <string name="accessibility_action_label_place_widget" msgid="1914197458644168978">"novietot atlasīto logrīku"</string> <string name="communal_widget_picker_title" msgid="1953369090475731663">"Bloķēšanas ekrāna logrīki"</string> <string name="communal_widget_picker_description" msgid="490515450110487871">"Jebkurš var skatīt logrīkus bloķēšanas ekrānā, pat ja planšetdators ir bloķēts."</string> - <!-- no translation found for accessibility_action_label_unselect_widget (1041811747619468698) --> - <skip /> + <string name="accessibility_action_label_unselect_widget" msgid="1041811747619468698">"noņemt logrīka atlasi"</string> <string name="communal_widgets_disclaimer_title" msgid="1150954395585308868">"Bloķēšanas ekrāna logrīki"</string> <string name="communal_widgets_disclaimer_text" msgid="1423545475160506349">"Lai atvērtu lietotni, izmantojot logrīku, jums būs jāapstiprina sava identitāte. Turklāt ņemiet vērā, ka ikviens var skatīt logrīkus, pat ja planšetdators ir bloķēts. Iespējams, daži logrīki nav paredzēti izmantošanai bloķēšanas ekrānā, un var nebūt droši tos šeit pievienot."</string> <string name="communal_widgets_disclaimer_button" msgid="4423059765740780753">"Labi"</string> @@ -557,10 +565,8 @@ <string name="media_projection_action_text" msgid="3634906766918186440">"Sākt tūlīt"</string> <string name="empty_shade_text" msgid="8935967157319717412">"Nav paziņojumu"</string> <string name="no_unseen_notif_text" msgid="395512586119868682">"Nav jaunu paziņojumu"</string> - <!-- no translation found for adaptive_notification_edu_hun_title (7790738150177329960) --> - <skip /> - <!-- no translation found for adaptive_notification_edu_hun_text (7743367744129536610) --> - <skip /> + <string name="adaptive_notification_edu_hun_title" msgid="7790738150177329960">"Nogaidīšanas periods paziņojumiem ir ieslēgts"</string> + <string name="adaptive_notification_edu_hun_text" msgid="7743367744129536610">"Saņemot par daudz paziņojumu uzreiz, skaļums un brīdinājumi tiek automātiski samazināti līdz 2 min."</string> <string name="go_to_adaptive_notification_settings" msgid="2423690125178298479">"Izslēgt"</string> <string name="unlock_to_see_notif_text" msgid="7439033907167561227">"Atbloķējiet vecāku paziņojumu skatīšanai"</string> <string name="quick_settings_disclosure_parental_controls" msgid="2114102871438223600">"Šo ierīci pārvalda viens no jūsu vecākiem."</string> @@ -1226,7 +1232,6 @@ <string name="accessibility_fingerprint_bouncer" msgid="7189102492498735519">"Nepieciešama autentifikācija. Pieskarieties pirksta nospieduma sensoram, lai veiktu autentificēšanu."</string> <string name="ongoing_phone_call_content_description" msgid="5332334388483099947">"Notiekošs tālruņa zvans"</string> <string name="mobile_data_settings_title" msgid="3955246641380064901">"Mobilie dati"</string> - <string name="preference_summary_default_combination" msgid="8453246369903749670">"<xliff:g id="STATE">%1$s</xliff:g>/<xliff:g id="NETWORKMODE">%2$s</xliff:g>"</string> <string name="mobile_data_connection_active" msgid="944490013299018227">"Ir izveidots savienojums"</string> <string name="mobile_data_temp_connection_active" msgid="4590222725908806824">"Īslaicīgi izveidots savienojums"</string> <string name="mobile_data_poor_connection" msgid="819617772268371434">"Vājš savienojums"</string> @@ -1380,7 +1385,10 @@ <string name="touchpad_tutorial_done_button" msgid="176168488821755503">"Gatavs"</string> <string name="touchpad_tutorial_gesture_done" msgid="4784438360736821255">"Lieliski!"</string> <string name="touchpad_back_gesture_action_title" msgid="7199067250654332735">"Atpakaļ"</string> - <string name="touchpad_back_gesture_guidance" msgid="4222430588599527272">"Lai pārietu atpakaļ, ar trim pirkstiem velciet pa kreisi vai pa labi jebkurā vietā uz skārienpaliktņa"</string> + <!-- no translation found for touchpad_back_gesture_guidance (6263750214998421587) --> + <skip /> + <!-- no translation found for touchpad_back_gesture_finished (5353616006999726249) --> + <skip /> <string name="touchpad_back_gesture_animation_content_description" msgid="2646107450922379918">"Attēls ar skārienpaliktni, uz kura trīs pirksti kustas pa labi un pa kreisi"</string> <string name="touchpad_back_gesture_screen_animation_content_description" msgid="4036267494237748710">"Ierīces ekrāns, kurā redzama animācija ar žestu pāriešanai atpakaļ"</string> <string name="keyboard_backlight_dialog_title" msgid="8273102932345564724">"Tastatūras fona apgaismojums"</string> @@ -1388,28 +1396,16 @@ <string name="home_controls_dream_label" msgid="6567105701292324257">"Mājas kontrolierīces"</string> <string name="home_controls_dream_description" msgid="4644150952104035789">"Ātra piekļuve mājas kontrolierīcēm ekrānsaudzētājā"</string> <string name="volume_undo_action" msgid="5815519725211877114">"Atsaukt"</string> - <!-- no translation found for back_edu_toast_content (4530314597378982956) --> - <skip /> - <!-- no translation found for home_edu_toast_content (3381071147871955415) --> - <skip /> - <!-- no translation found for overview_edu_toast_content (5797030644017804518) --> - <skip /> - <!-- no translation found for all_apps_edu_toast_content (8807496014667211562) --> - <skip /> - <!-- no translation found for back_edu_notification_title (5624780717751357278) --> - <skip /> - <!-- no translation found for back_edu_notification_content (2497557451540954068) --> - <skip /> - <!-- no translation found for home_edu_notification_title (6097902076909654045) --> - <skip /> - <!-- no translation found for home_edu_notification_content (6631697734535766588) --> - <skip /> - <!-- no translation found for overview_edu_notification_title (1265824157319562406) --> - <skip /> - <!-- no translation found for overview_edu_notification_content (3578204677648432500) --> - <skip /> - <!-- no translation found for all_apps_edu_notification_title (372262997265569063) --> - <skip /> - <!-- no translation found for all_apps_edu_notification_content (3255070575694025585) --> - <skip /> + <string name="back_edu_toast_content" msgid="4530314597378982956">"Lai atgrieztos, ar trīs pirkstiem velciet pa kreisi vai pa labi jebkurā vietā uz skārienpaliktņa."</string> + <string name="home_edu_toast_content" msgid="3381071147871955415">"Lai pārietu uz sākuma ekrāna, ar trīs pirkstiem uz skārienpaliktņa velciet augšup."</string> + <string name="overview_edu_toast_content" msgid="5797030644017804518">"Lai skatītu nesenās lietotnes, ar trīs pirkstiem uz skārienpaliktņa velciet augšup un turiet."</string> + <string name="all_apps_edu_toast_content" msgid="8807496014667211562">"Lai skatītu visas savas lietotnes, tastatūrā nospiediet darbību taustiņu."</string> + <string name="back_edu_notification_title" msgid="5624780717751357278">"Atgriešanās, izmantojot skārienpaliktni"</string> + <string name="back_edu_notification_content" msgid="2497557451540954068">"Ar trīs pirkstiem velciet pa kreisi vai pa labi. Lai apgūtu citus žestus, pieskarieties šeit."</string> + <string name="home_edu_notification_title" msgid="6097902076909654045">"Pāriešana uz sākuma ekrānu, izmantojot skārienpaliktni"</string> + <string name="home_edu_notification_content" msgid="6631697734535766588">"Ar trīs pirkstiem velciet augšup. Lai apgūtu citus žestus, pieskarieties šeit."</string> + <string name="overview_edu_notification_title" msgid="1265824157319562406">"Pēdējo lietotņu skatīšana, izmantojot skārienpaliktni"</string> + <string name="overview_edu_notification_content" msgid="3578204677648432500">"Ar trīs pirkstiem velciet augšup un turiet. Lai apgūtu citus žestus, pieskarieties šeit."</string> + <string name="all_apps_edu_notification_title" msgid="372262997265569063">"Visu lietotņu skatīšana, izmantojot tastatūru"</string> + <string name="all_apps_edu_notification_content" msgid="3255070575694025585">"Jebkurā laikā varat nospiest darbību taustiņu. Lai apgūtu citus žestus, pieskarieties šeit."</string> </resources> diff --git a/packages/SystemUI/res/values-lv/tiles_states_strings.xml b/packages/SystemUI/res/values-lv/tiles_states_strings.xml index 4103c0aef9e3..c65a1d429492 100644 --- a/packages/SystemUI/res/values-lv/tiles_states_strings.xml +++ b/packages/SystemUI/res/values-lv/tiles_states_strings.xml @@ -56,11 +56,6 @@ <item msgid="5376619709702103243">"Izslēgts"</item> <item msgid="4875147066469902392">"Ieslēgts"</item> </string-array> - <string-array name="tile_states_modes"> - <item msgid="7764936419245199023">"Nav pieejams"</item> - <item msgid="2004750556637773692">"Izslēgts"</item> - <item msgid="8968530753931637871">"Ieslēgts"</item> - </string-array> <string-array name="tile_states_flashlight"> <item msgid="3465257127433353857">"Nav pieejams"</item> <item msgid="5044688398303285224">"Izslēgts"</item> diff --git a/packages/SystemUI/res/values-mk/strings.xml b/packages/SystemUI/res/values-mk/strings.xml index 052945e61b77..68f9a9da2985 100644 --- a/packages/SystemUI/res/values-mk/strings.xml +++ b/packages/SystemUI/res/values-mk/strings.xml @@ -388,6 +388,9 @@ <string name="performance" msgid="6552785217174378320">"Изведба"</string> <string name="user_interface" msgid="3712869377953950887">"Кориснички интерфејс"</string> <string name="thermal" msgid="6758074791325414831">"Термално"</string> + <string name="custom" msgid="3337456985275158299">"Приспособено"</string> + <string name="custom_trace_settings_dialog_title" msgid="2608570500144830554">"Приспособени поставки за следење"</string> + <string name="restore_default" msgid="5259420807486239755">"Врати на стандардно"</string> <string name="quick_settings_onehanded_label" msgid="2416537930246274991">"Режим со една рака"</string> <string name="quick_settings_hearing_devices_label" msgid="7277170419679404129">"Слушни апарати"</string> <string name="quick_settings_hearing_devices_connected" msgid="6519069502397037781">"Активно"</string> @@ -429,9 +432,13 @@ <string name="zen_modes_dialog_title" msgid="4159138230418567383">"Приоритетни режими"</string> <string name="zen_modes_dialog_done" msgid="6654130880256438950">"Готово"</string> <string name="zen_modes_dialog_settings" msgid="2310248023728936697">"Поставки"</string> - <!-- no translation found for zen_mode_on (9085304934016242591) --> + <string name="zen_mode_on" msgid="9085304934016242591">"Вклучено"</string> + <string name="zen_mode_off" msgid="1736604456618147306">"Исклучено"</string> + <!-- no translation found for zen_mode_set_up (7457957033034460064) --> <skip /> - <!-- no translation found for zen_mode_off (1736604456618147306) --> + <!-- no translation found for zen_mode_no_manual_invocation (1769975741344633672) --> + <skip /> + <!-- no translation found for zen_mode_active_modes (1625850411578488856) --> <skip /> <string name="zen_priority_introduction" msgid="3159291973383796646">"Нема да ве вознемируваат звуци и вибрации, освен од аларми, потсетници, настани и повикувачи што ќе ги наведете. Сѐ уште ќе слушате сѐ што ќе изберете да пуштите, како музика, видеа и игри."</string> <string name="zen_alarms_introduction" msgid="3987266042682300470">"Нема да ве вознемируваат звуци и вибрации, освен од аларми. Сѐ уште ќе слушате сѐ што ќе изберете да пуштите, како музика, видеа и игри."</string> @@ -471,6 +478,8 @@ <string name="keyguard_indication_charging_time_slowly" msgid="301936949731705417">"<xliff:g id="PERCENTAGE">%2$s</xliff:g> • Се полни бавно • Полна по <xliff:g id="CHARGING_TIME_LEFT">%1$s</xliff:g>"</string> <string name="keyguard_indication_charging_time_dock" msgid="3149328898931741271">"<xliff:g id="PERCENTAGE">%2$s</xliff:g> • Се полни • Полна по <xliff:g id="CHARGING_TIME_LEFT">%1$s</xliff:g>"</string> <string name="accessibility_action_open_communal_hub" msgid="3081702792413787849">"Виџети на заклучен екран"</string> + <!-- no translation found for accessibility_announcement_communal_widget_added (6911593106099328271) --> + <skip /> <string name="communal_tutorial_indicator_text" msgid="4503010353591430123">"Повлечете налево за да го започнете заедничкото упатство"</string> <string name="cta_tile_button_to_open_widget_editor" msgid="3871562362382963878">"Приспособете"</string> <string name="cta_tile_button_to_dismiss" msgid="3377597875997861754">"Отфрли"</string> @@ -499,8 +508,7 @@ <string name="accessibility_action_label_place_widget" msgid="1914197458644168978">"поставете го избраниот виџет"</string> <string name="communal_widget_picker_title" msgid="1953369090475731663">"Виџети на заклучен екран"</string> <string name="communal_widget_picker_description" msgid="490515450110487871">"Секој може да гледа виџети на заклучениот екран, дури и ако таблетот е заклучен."</string> - <!-- no translation found for accessibility_action_label_unselect_widget (1041811747619468698) --> - <skip /> + <string name="accessibility_action_label_unselect_widget" msgid="1041811747619468698">"поништи го изборот на виџетот"</string> <string name="communal_widgets_disclaimer_title" msgid="1150954395585308868">"Виџети на заклучен екран"</string> <string name="communal_widgets_disclaimer_text" msgid="1423545475160506349">"За да отворите апликација со помош на виџет, ќе треба да потврдите дека сте вие. Покрај тоа, имајте предвид дека секој може да ги гледа виџетите, дури и кога вашиот таблет е заклучен. Некои виџети можеби не се наменети за вашиот заклучен екран, па можеби не е безбедно да се додадат овде."</string> <string name="communal_widgets_disclaimer_button" msgid="4423059765740780753">"Сфатив"</string> @@ -557,10 +565,8 @@ <string name="media_projection_action_text" msgid="3634906766918186440">"Започни сега"</string> <string name="empty_shade_text" msgid="8935967157319717412">"Нема известувања"</string> <string name="no_unseen_notif_text" msgid="395512586119868682">"Нема нови известувања"</string> - <!-- no translation found for adaptive_notification_edu_hun_title (7790738150177329960) --> - <skip /> - <!-- no translation found for adaptive_notification_edu_hun_text (7743367744129536610) --> - <skip /> + <string name="adaptive_notification_edu_hun_title" msgid="7790738150177329960">"„Подискретни известувања“ е вклучена"</string> + <string name="adaptive_notification_edu_hun_text" msgid="7743367744129536610">"Јачината на звукот и известувањата на уредот се намалуваат автоматски до 2 минути кога добивате премногу известувања одеднаш."</string> <string name="go_to_adaptive_notification_settings" msgid="2423690125178298479">"Исклучи"</string> <string name="unlock_to_see_notif_text" msgid="7439033907167561227">"Отклучете за да ги видите старите известувања"</string> <string name="quick_settings_disclosure_parental_controls" msgid="2114102871438223600">"Родителот управува со уредов"</string> @@ -1226,7 +1232,6 @@ <string name="accessibility_fingerprint_bouncer" msgid="7189102492498735519">"Потребна е проверка. Допрете го сензорот за отпечаток за да автентицирате."</string> <string name="ongoing_phone_call_content_description" msgid="5332334388483099947">"Тековен телефонски повик"</string> <string name="mobile_data_settings_title" msgid="3955246641380064901">"Мобилен интернет"</string> - <string name="preference_summary_default_combination" msgid="8453246369903749670">"<xliff:g id="STATE">%1$s</xliff:g>/<xliff:g id="NETWORKMODE">%2$s</xliff:g>"</string> <string name="mobile_data_connection_active" msgid="944490013299018227">"Поврзано"</string> <string name="mobile_data_temp_connection_active" msgid="4590222725908806824">"Привремено поврзано"</string> <string name="mobile_data_poor_connection" msgid="819617772268371434">"Слаба интернет-врска"</string> @@ -1380,7 +1385,10 @@ <string name="touchpad_tutorial_done_button" msgid="176168488821755503">"Готово"</string> <string name="touchpad_tutorial_gesture_done" msgid="4784438360736821255">"Одлично сторено!"</string> <string name="touchpad_back_gesture_action_title" msgid="7199067250654332735">"Назад"</string> - <string name="touchpad_back_gesture_guidance" msgid="4222430588599527272">"За да се вратите назад, повлечете налево или надесно со три прста каде било на допирната подлога."</string> + <!-- no translation found for touchpad_back_gesture_guidance (6263750214998421587) --> + <skip /> + <!-- no translation found for touchpad_back_gesture_finished (5353616006999726249) --> + <skip /> <string name="touchpad_back_gesture_animation_content_description" msgid="2646107450922379918">"Допирната подлога покажува три прста што се движат десно и лево"</string> <string name="touchpad_back_gesture_screen_animation_content_description" msgid="4036267494237748710">"Екранот на уредот покажува анимација за движење назад"</string> <string name="keyboard_backlight_dialog_title" msgid="8273102932345564724">"Осветлување на тастатура"</string> @@ -1388,28 +1396,16 @@ <string name="home_controls_dream_label" msgid="6567105701292324257">"Контроли за домот"</string> <string name="home_controls_dream_description" msgid="4644150952104035789">"Контролите за домот како штедач на екран"</string> <string name="volume_undo_action" msgid="5815519725211877114">"Врати"</string> - <!-- no translation found for back_edu_toast_content (4530314597378982956) --> - <skip /> - <!-- no translation found for home_edu_toast_content (3381071147871955415) --> - <skip /> - <!-- no translation found for overview_edu_toast_content (5797030644017804518) --> - <skip /> - <!-- no translation found for all_apps_edu_toast_content (8807496014667211562) --> - <skip /> - <!-- no translation found for back_edu_notification_title (5624780717751357278) --> - <skip /> - <!-- no translation found for back_edu_notification_content (2497557451540954068) --> - <skip /> - <!-- no translation found for home_edu_notification_title (6097902076909654045) --> - <skip /> - <!-- no translation found for home_edu_notification_content (6631697734535766588) --> - <skip /> - <!-- no translation found for overview_edu_notification_title (1265824157319562406) --> - <skip /> - <!-- no translation found for overview_edu_notification_content (3578204677648432500) --> - <skip /> - <!-- no translation found for all_apps_edu_notification_title (372262997265569063) --> - <skip /> - <!-- no translation found for all_apps_edu_notification_content (3255070575694025585) --> - <skip /> + <string name="back_edu_toast_content" msgid="4530314597378982956">"За да се вратите назад, повлечете налево или надесно со три прста на допирната подлога"</string> + <string name="home_edu_toast_content" msgid="3381071147871955415">"За да одите на почетниот екран, повлечете нагоре со три прста на допирната подлога"</string> + <string name="overview_edu_toast_content" msgid="5797030644017804518">"За да ги видите скорешните апликации, повлечете нагоре и задржете со три прста на допирната подлога"</string> + <string name="all_apps_edu_toast_content" msgid="8807496014667211562">"Притиснете го копчето за дејство на тастатурата за да ги видите сите апликации"</string> + <string name="back_edu_notification_title" msgid="5624780717751357278">"Користете ја допирната подлога за да се вратите назад"</string> + <string name="back_edu_notification_content" msgid="2497557451540954068">"Повлечете налево или надесно со три прста. Допрете за да научите повеќе движења."</string> + <string name="home_edu_notification_title" msgid="6097902076909654045">"Користете ја допирната подлога за да одите на почетниот екран"</string> + <string name="home_edu_notification_content" msgid="6631697734535766588">"Повлечете нагоре со три прста. Допрете за да научите повеќе движења."</string> + <string name="overview_edu_notification_title" msgid="1265824157319562406">"Користете ја допирната подлога за да ги видите скорешните апликации"</string> + <string name="overview_edu_notification_content" msgid="3578204677648432500">"Повлечете нагоре и задржете со три прста. Допрете за да научите повеќе движења."</string> + <string name="all_apps_edu_notification_title" msgid="372262997265569063">"Користете ја тастатурата за да ги видите сите апликации"</string> + <string name="all_apps_edu_notification_content" msgid="3255070575694025585">"Притиснете го копчето за дејство кога сакате. Допрете за да научите повеќе движења."</string> </resources> diff --git a/packages/SystemUI/res/values-mk/tiles_states_strings.xml b/packages/SystemUI/res/values-mk/tiles_states_strings.xml index 5e9f5bd13a90..a8d96950b6f8 100644 --- a/packages/SystemUI/res/values-mk/tiles_states_strings.xml +++ b/packages/SystemUI/res/values-mk/tiles_states_strings.xml @@ -56,11 +56,6 @@ <item msgid="5376619709702103243">"Исклучено"</item> <item msgid="4875147066469902392">"Вклучено"</item> </string-array> - <string-array name="tile_states_modes"> - <item msgid="7764936419245199023">"Недостапно"</item> - <item msgid="2004750556637773692">"Исклучено"</item> - <item msgid="8968530753931637871">"Вклучено"</item> - </string-array> <string-array name="tile_states_flashlight"> <item msgid="3465257127433353857">"Недостапно"</item> <item msgid="5044688398303285224">"Исклучено"</item> diff --git a/packages/SystemUI/res/values-ml/strings.xml b/packages/SystemUI/res/values-ml/strings.xml index b43be14f686b..8711604d09c7 100644 --- a/packages/SystemUI/res/values-ml/strings.xml +++ b/packages/SystemUI/res/values-ml/strings.xml @@ -388,6 +388,9 @@ <string name="performance" msgid="6552785217174378320">"പ്രകടനം"</string> <string name="user_interface" msgid="3712869377953950887">"ഉപയോക്തൃ ഇന്റർഫേസ്"</string> <string name="thermal" msgid="6758074791325414831">"തെർമൽ"</string> + <string name="custom" msgid="3337456985275158299">"ഇഷ്ടാനുസൃതം"</string> + <string name="custom_trace_settings_dialog_title" msgid="2608570500144830554">"ഇഷ്ടാനുസൃത അടയാള ക്രമീകരണം"</string> + <string name="restore_default" msgid="5259420807486239755">"ഡിഫോൾട്ട് പുനഃസ്ഥാപിക്കുക"</string> <string name="quick_settings_onehanded_label" msgid="2416537930246274991">"ഒറ്റക്കൈ മോഡ്"</string> <string name="quick_settings_hearing_devices_label" msgid="7277170419679404129">"കേൾവിക്കുള്ള ഉപകരണങ്ങൾ"</string> <string name="quick_settings_hearing_devices_connected" msgid="6519069502397037781">"സജീവം"</string> @@ -429,9 +432,13 @@ <string name="zen_modes_dialog_title" msgid="4159138230418567383">"മുൻഗണനാ മോഡുകൾ"</string> <string name="zen_modes_dialog_done" msgid="6654130880256438950">"ശരി"</string> <string name="zen_modes_dialog_settings" msgid="2310248023728936697">"ക്രമീകരണം"</string> - <!-- no translation found for zen_mode_on (9085304934016242591) --> + <string name="zen_mode_on" msgid="9085304934016242591">"ഓണാണ്"</string> + <string name="zen_mode_off" msgid="1736604456618147306">"ഓഫാണ്"</string> + <!-- no translation found for zen_mode_set_up (7457957033034460064) --> <skip /> - <!-- no translation found for zen_mode_off (1736604456618147306) --> + <!-- no translation found for zen_mode_no_manual_invocation (1769975741344633672) --> + <skip /> + <!-- no translation found for zen_mode_active_modes (1625850411578488856) --> <skip /> <string name="zen_priority_introduction" msgid="3159291973383796646">"നിങ്ങൾ സജ്ജീകരിച്ച അലാറങ്ങൾ, റിമൈൻഡറുകൾ, ഇവന്റുകൾ, കോളർമാർ എന്നിവയിൽ നിന്നുള്ള ശബ്ദങ്ങളും വൈബ്രേഷനുകളുമൊഴികെ മറ്റൊന്നും നിങ്ങളെ ശല്യപ്പെടുത്തുകയില്ല. സംഗീതം, വീഡിയോകൾ, ഗെയിമുകൾ എന്നിവയുൾപ്പെടെ പ്ലേ ചെയ്യുന്നതെന്തും നിങ്ങൾക്ക് തുടർന്നും കേൾക്കാൻ കഴിയും."</string> <string name="zen_alarms_introduction" msgid="3987266042682300470">"അലാറങ്ങളിൽ നിന്നുള്ള ശബ്ദങ്ങളും വൈബ്രേഷനുകളുമൊഴികെ മറ്റൊന്നും നിങ്ങളെ ശല്യപ്പെടുത്തുകയില്ല. സംഗീതം, വീഡിയോകൾ, ഗെയിമുകൾ എന്നിവയുൾപ്പെടെ പ്ലേ ചെയ്യുന്നതെന്തും നിങ്ങൾക്ക് തുടർന്നും കേൾക്കാൻ കഴിയും."</string> @@ -471,6 +478,8 @@ <string name="keyguard_indication_charging_time_slowly" msgid="301936949731705417">"<xliff:g id="PERCENTAGE">%2$s</xliff:g> • പതുക്കെ ചാർജ് ചെയ്യുന്നു • <xliff:g id="CHARGING_TIME_LEFT">%1$s</xliff:g>-ൽ പൂർത്തിയാകും"</string> <string name="keyguard_indication_charging_time_dock" msgid="3149328898931741271">"<xliff:g id="PERCENTAGE">%2$s</xliff:g> • ചാർജ് ചെയ്യുന്നു • <xliff:g id="CHARGING_TIME_LEFT">%1$s</xliff:g>-ൽ പൂർത്തിയാകും"</string> <string name="accessibility_action_open_communal_hub" msgid="3081702792413787849">"ലോക്ക് സ്ക്രീനിൽ വിജറ്റുകൾ"</string> + <!-- no translation found for accessibility_announcement_communal_widget_added (6911593106099328271) --> + <skip /> <string name="communal_tutorial_indicator_text" msgid="4503010353591430123">"കമ്മ്യൂണൽ ട്യൂട്ടോറിയൽ ആരംഭിക്കാൻ ഇടത്തോട്ട് സ്വൈപ്പ് ചെയ്യുക"</string> <string name="cta_tile_button_to_open_widget_editor" msgid="3871562362382963878">"ഇഷ്ടാനുസൃതമാക്കുക"</string> <string name="cta_tile_button_to_dismiss" msgid="3377597875997861754">"ഡിസ്മിസ് ചെയ്യുക"</string> @@ -499,8 +508,7 @@ <string name="accessibility_action_label_place_widget" msgid="1914197458644168978">"തിരഞ്ഞെടുത്ത വിജറ്റ് നൽകുക"</string> <string name="communal_widget_picker_title" msgid="1953369090475731663">"ലോക്ക് സ്ക്രീൻ വിജറ്റുകൾ"</string> <string name="communal_widget_picker_description" msgid="490515450110487871">"ടാബ്ലെറ്റ് ലോക്കാണെങ്കിൽ പോലും ലോക്ക് സ്ക്രീനിൽ ആർക്കും വിജറ്റുകൾ കാണാം."</string> - <!-- no translation found for accessibility_action_label_unselect_widget (1041811747619468698) --> - <skip /> + <string name="accessibility_action_label_unselect_widget" msgid="1041811747619468698">"വിജറ്റ് തിരഞ്ഞെടുത്തത് മാറ്റുക"</string> <string name="communal_widgets_disclaimer_title" msgid="1150954395585308868">"ലോക്ക് സ്ക്രീൻ വിജറ്റുകൾ"</string> <string name="communal_widgets_disclaimer_text" msgid="1423545475160506349">"വിജറ്റ് ഉപയോഗിച്ച് ഒരു ആപ്പ് തുറക്കാൻ, ഇത് നിങ്ങൾ തന്നെയാണെന്ന് പരിശോധിച്ചുറപ്പിക്കേണ്ടതുണ്ട്. നിങ്ങളുടെ ടാബ്ലെറ്റ് ലോക്കായിരിക്കുമ്പോഴും എല്ലാവർക്കും അത് കാണാനാകുമെന്നതും ഓർക്കുക. ചില വിജറ്റുകൾ നിങ്ങളുടെ ലോക്ക് സ്ക്രീനിന് ഉള്ളതായിരിക്കില്ല, അവ ഇവിടെ ചേർക്കുന്നത് സുരക്ഷിതവുമായിരിക്കില്ല."</string> <string name="communal_widgets_disclaimer_button" msgid="4423059765740780753">"മനസ്സിലായി"</string> @@ -557,10 +565,8 @@ <string name="media_projection_action_text" msgid="3634906766918186440">"ഇപ്പോൾ ആരംഭിക്കുക"</string> <string name="empty_shade_text" msgid="8935967157319717412">"അറിയിപ്പുകൾ ഒന്നുമില്ല"</string> <string name="no_unseen_notif_text" msgid="395512586119868682">"പുതിയ അറിയിപ്പുകളൊന്നുമില്ല"</string> - <!-- no translation found for adaptive_notification_edu_hun_title (7790738150177329960) --> - <skip /> - <!-- no translation found for adaptive_notification_edu_hun_text (7743367744129536610) --> - <skip /> + <string name="adaptive_notification_edu_hun_title" msgid="7790738150177329960">"അറിയിപ്പിന്റെ ശബ്ദം കുറയ്ക്കൽ ഓണാണ്"</string> + <string name="adaptive_notification_edu_hun_text" msgid="7743367744129536610">"നിരവധി അറിയിപ്പ് ഒരുമിച്ച് ലഭിക്കുമ്പോൾ, ഉപകരണത്തിന്റെ ശബ്ദവും മുന്നറിയിപ്പും 2 മിനിറ്റ് വരെ സ്വയമേവ കുറയ്ക്കും."</string> <string name="go_to_adaptive_notification_settings" msgid="2423690125178298479">"ഓഫാക്കുക"</string> <string name="unlock_to_see_notif_text" msgid="7439033907167561227">"പഴയ അറിയിപ്പുകൾ കാണാൻ അൺലോക്ക് ചെയ്യുക"</string> <string name="quick_settings_disclosure_parental_controls" msgid="2114102871438223600">"ഈ ഉപകരണം മാനേജ് ചെയ്യുന്നത് നിങ്ങളുടെ രക്ഷിതാവാണ്"</string> @@ -1226,7 +1232,6 @@ <string name="accessibility_fingerprint_bouncer" msgid="7189102492498735519">"പരിശോധിച്ചുറപ്പിക്കേണ്ടതുണ്ട്. പരിശോധിച്ചുറപ്പിക്കാൻ, വിരലടയാള സെൻസറിൽ സ്പർശിക്കുക."</string> <string name="ongoing_phone_call_content_description" msgid="5332334388483099947">"സജീവമായ ഫോൺ കോൾ"</string> <string name="mobile_data_settings_title" msgid="3955246641380064901">"മൊബൈൽ ഡാറ്റ"</string> - <string name="preference_summary_default_combination" msgid="8453246369903749670">"<xliff:g id="STATE">%1$s</xliff:g> / <xliff:g id="NETWORKMODE">%2$s</xliff:g>"</string> <string name="mobile_data_connection_active" msgid="944490013299018227">"കണക്റ്റ് ചെയ്തു"</string> <string name="mobile_data_temp_connection_active" msgid="4590222725908806824">"താൽക്കാലികമായി കണക്റ്റ് ചെയ്തിരിക്കുന്നു"</string> <string name="mobile_data_poor_connection" msgid="819617772268371434">"ദുർബലമായ കണക്ഷൻ"</string> @@ -1380,7 +1385,10 @@ <string name="touchpad_tutorial_done_button" msgid="176168488821755503">"പൂർത്തിയായി"</string> <string name="touchpad_tutorial_gesture_done" msgid="4784438360736821255">"കൊള്ളാം!"</string> <string name="touchpad_back_gesture_action_title" msgid="7199067250654332735">"മടങ്ങുക"</string> - <string name="touchpad_back_gesture_guidance" msgid="4222430588599527272">"തിരികെ പോകാൻ, ടച്ച്പാഡിൽ എവിടെയെങ്കിലും മൂന്ന് വിരലുകൾ ഉപയോഗിച്ച് ഇടത്തേക്കോ വലത്തേക്കോ സ്വൈപ്പ് ചെയ്യുക."</string> + <!-- no translation found for touchpad_back_gesture_guidance (6263750214998421587) --> + <skip /> + <!-- no translation found for touchpad_back_gesture_finished (5353616006999726249) --> + <skip /> <string name="touchpad_back_gesture_animation_content_description" msgid="2646107450922379918">"വലത്തേക്കും ഇടത്തേക്കും ചലിക്കുന്ന മൂന്ന് വിരലുകൾ കാണിക്കുന്ന ടച്ച്പാഡ്"</string> <string name="touchpad_back_gesture_screen_animation_content_description" msgid="4036267494237748710">"ബാക്ക് ജെസ്ച്ചറിനായി ആനിമേഷൻ കാണിക്കുന്ന ഉപകരണ സ്ക്രീൻ"</string> <string name="keyboard_backlight_dialog_title" msgid="8273102932345564724">"കീബോഡ് ബാക്ക്ലൈറ്റ്"</string> @@ -1388,28 +1396,16 @@ <string name="home_controls_dream_label" msgid="6567105701292324257">"ഹോം കൺട്രോളുകൾ"</string> <string name="home_controls_dream_description" msgid="4644150952104035789">"സ്ക്രീൻസേവറായി ഹോം കൺട്രോളുകൾ പെട്ടെന്ന് ആക്സസ് ചെയ്യൂ"</string> <string name="volume_undo_action" msgid="5815519725211877114">"പഴയപടിയാക്കുക"</string> - <!-- no translation found for back_edu_toast_content (4530314597378982956) --> - <skip /> - <!-- no translation found for home_edu_toast_content (3381071147871955415) --> - <skip /> - <!-- no translation found for overview_edu_toast_content (5797030644017804518) --> - <skip /> - <!-- no translation found for all_apps_edu_toast_content (8807496014667211562) --> - <skip /> - <!-- no translation found for back_edu_notification_title (5624780717751357278) --> - <skip /> - <!-- no translation found for back_edu_notification_content (2497557451540954068) --> - <skip /> - <!-- no translation found for home_edu_notification_title (6097902076909654045) --> - <skip /> - <!-- no translation found for home_edu_notification_content (6631697734535766588) --> - <skip /> - <!-- no translation found for overview_edu_notification_title (1265824157319562406) --> - <skip /> - <!-- no translation found for overview_edu_notification_content (3578204677648432500) --> - <skip /> - <!-- no translation found for all_apps_edu_notification_title (372262997265569063) --> - <skip /> - <!-- no translation found for all_apps_edu_notification_content (3255070575694025585) --> - <skip /> + <string name="back_edu_toast_content" msgid="4530314597378982956">"തിരികെ പോകാൻ, മൂന്ന് വിരലുകൾ ഉപയോഗിച്ച് ടച്ച്പാഡിൽ ഇടത്തേക്കോ വലത്തേക്കോ സ്വൈപ്പ് ചെയ്യുക"</string> + <string name="home_edu_toast_content" msgid="3381071147871955415">"ഹോമിലേക്ക് പോകാൻ, മൂന്ന് വിരലുകൾ ഉപയോഗിച്ച് ടച്ച്പാഡിൽ മുകളിലേക്ക് സ്വൈപ്പ് ചെയ്യുക"</string> + <string name="overview_edu_toast_content" msgid="5797030644017804518">"അടുത്തിടെ ഉപയോഗിച്ച ആപ്പുകൾ കാണാൻ, മൂന്ന് വിരലുകൾ ഉപയോഗിച്ച് ടച്ച്പാഡിൽ സ്വൈപ്പ് ചെയ്ത് പിടിക്കുക"</string> + <string name="all_apps_edu_toast_content" msgid="8807496014667211562">"എല്ലാ ആപ്പുകളും കാണാൻ, നിങ്ങളുടെ കീബോർഡിലെ ആക്ഷൻ കീ അമർത്തുക"</string> + <string name="back_edu_notification_title" msgid="5624780717751357278">"തിരികെ പോകാൻ നിങ്ങളുടെ ടച്ച്പാഡ് ഉപയോഗിക്കുക"</string> + <string name="back_edu_notification_content" msgid="2497557451540954068">"മൂന്ന് വിരലുകളാൽ ഇടത്തേക്കോ വലത്തേക്കോ സ്വൈപ്പുചെയ്യൂ. കൂടുതൽ ജെസ്ച്ചറുകൾ മനസ്സിലാക്കാൻ ടാപ്പ് ചെയ്യുക."</string> + <string name="home_edu_notification_title" msgid="6097902076909654045">"ഹോമിലേക്ക് പോകാൻ നിങ്ങളുടെ ടച്ച്പാഡ് ഉപയോഗിക്കുക"</string> + <string name="home_edu_notification_content" msgid="6631697734535766588">"മൂന്ന് വിരലുകൾ കൊണ്ട് മുകളിലേക്ക് സ്വൈപ്പ് ചെയ്യുക. കൂടുതൽ ജെസ്ച്ചറുകൾ മനസ്സിലാക്കാൻ ടാപ്പ് ചെയ്യുക."</string> + <string name="overview_edu_notification_title" msgid="1265824157319562406">"അടുത്തിടെ ഉപയോഗിച്ച ആപ്പുകൾ കാണാൻ നിങ്ങളുടെ ടച്ച്പാഡ് ഉപയോഗിക്കുക"</string> + <string name="overview_edu_notification_content" msgid="3578204677648432500">"മൂന്ന് വിരലുകൾ കൊണ്ട് മുകളിലേക്ക് സ്വൈപ്പ് ചെയ്ത് പിടിക്കുക. കൂടുതൽ ജെസ്ച്ചറുകൾ മനസ്സിലാക്കാൻ ടാപ്പ് ചെയ്യുക."</string> + <string name="all_apps_edu_notification_title" msgid="372262997265569063">"എല്ലാ ആപ്പുകളും കാണാൻ നിങ്ങളുടെ കീബോർഡ് ഉപയോഗിക്കുക"</string> + <string name="all_apps_edu_notification_content" msgid="3255070575694025585">"ഏതുസമയത്തും ആക്ഷൻ കീ അമർത്തുക. കൂടുതൽ ജെസ്ച്ചറുകൾ മനസ്സിലാക്കാൻ ടാപ്പ് ചെയ്യുക."</string> </resources> diff --git a/packages/SystemUI/res/values-ml/tiles_states_strings.xml b/packages/SystemUI/res/values-ml/tiles_states_strings.xml index 6b4e9378308c..609fdde3f5de 100644 --- a/packages/SystemUI/res/values-ml/tiles_states_strings.xml +++ b/packages/SystemUI/res/values-ml/tiles_states_strings.xml @@ -56,11 +56,6 @@ <item msgid="5376619709702103243">"ഓഫാണ്"</item> <item msgid="4875147066469902392">"ഓണാണ്"</item> </string-array> - <string-array name="tile_states_modes"> - <item msgid="7764936419245199023">"ലഭ്യമല്ല"</item> - <item msgid="2004750556637773692">"ഓഫാണ്"</item> - <item msgid="8968530753931637871">"ഓണാണ്"</item> - </string-array> <string-array name="tile_states_flashlight"> <item msgid="3465257127433353857">"ലഭ്യമല്ല"</item> <item msgid="5044688398303285224">"ഓഫാണ്"</item> diff --git a/packages/SystemUI/res/values-mn/strings.xml b/packages/SystemUI/res/values-mn/strings.xml index 673628818a34..95b4e3fe88c1 100644 --- a/packages/SystemUI/res/values-mn/strings.xml +++ b/packages/SystemUI/res/values-mn/strings.xml @@ -131,7 +131,7 @@ <string name="screenrecord_stop_dialog_message_specific_app" msgid="5995770227684523244">"Та одоогоор <xliff:g id="APP_NAME">%1$s</xliff:g>-г бичиж байна"</string> <string name="screenrecord_stop_dialog_button" msgid="2883812564938194350">"Бичихийг зогсоох"</string> <string name="share_to_app_chip_accessibility_label" msgid="4210256229976947065">"Дэлгэцийг хуваалцаж байна"</string> - <string name="share_to_app_stop_dialog_title" msgid="9212915050910250438">"Дэлгэцийг хуваалцахыг зогсоох уу?"</string> + <string name="share_to_app_stop_dialog_title" msgid="9212915050910250438">"Дэлгэц хуваалцахыг зогсоох уу?"</string> <string name="share_to_app_stop_dialog_message_entire_screen_with_host_app" msgid="522823522115375414">"Та одоогоор дэлгэцээ бүтнээр нь <xliff:g id="HOST_APP_NAME">%1$s</xliff:g>-тай хуваалцаж байна"</string> <string name="share_to_app_stop_dialog_message_entire_screen" msgid="5090115386271179270">"Та одоогоор дэлгэцээ бүтнээр нь нэг апптай хуваалцаж байна"</string> <string name="share_to_app_stop_dialog_message_single_app_specific" msgid="5923772039347985172">"Та одоогоор <xliff:g id="APP_BEING_SHARED_NAME">%1$s</xliff:g>-г хуваалцаж байна"</string> @@ -388,6 +388,9 @@ <string name="performance" msgid="6552785217174378320">"Гүйцэтгэл"</string> <string name="user_interface" msgid="3712869377953950887">"Хэрэглэгчийн интерфейс"</string> <string name="thermal" msgid="6758074791325414831">"Дулааны"</string> + <string name="custom" msgid="3337456985275158299">"Захиалгат"</string> + <string name="custom_trace_settings_dialog_title" msgid="2608570500144830554">"Захиалгат ул мөрийн тохиргоо"</string> + <string name="restore_default" msgid="5259420807486239755">"Өгөгдмөлийг сэргээх"</string> <string name="quick_settings_onehanded_label" msgid="2416537930246274991">"Нэг гарын горим"</string> <string name="quick_settings_hearing_devices_label" msgid="7277170419679404129">"Сонсголын төхөөрөмжүүд"</string> <string name="quick_settings_hearing_devices_connected" msgid="6519069502397037781">"Идэвхтэй"</string> @@ -429,9 +432,13 @@ <string name="zen_modes_dialog_title" msgid="4159138230418567383">"Чухал байдлаар нь ангилах горим"</string> <string name="zen_modes_dialog_done" msgid="6654130880256438950">"Болсон"</string> <string name="zen_modes_dialog_settings" msgid="2310248023728936697">"Тохиргоо"</string> - <!-- no translation found for zen_mode_on (9085304934016242591) --> + <string name="zen_mode_on" msgid="9085304934016242591">"Асаалттай"</string> + <string name="zen_mode_off" msgid="1736604456618147306">"Унтраалттай"</string> + <!-- no translation found for zen_mode_set_up (7457957033034460064) --> <skip /> - <!-- no translation found for zen_mode_off (1736604456618147306) --> + <!-- no translation found for zen_mode_no_manual_invocation (1769975741344633672) --> + <skip /> + <!-- no translation found for zen_mode_active_modes (1625850411578488856) --> <skip /> <string name="zen_priority_introduction" msgid="3159291973383796646">"Танд сэрүүлэг, сануулга, арга хэмжээ, таны сонгосон дуудлага илгээгчээс бусад дуу, чичиргээ саад болохгүй. Та хөгжим, видео, тоглоом зэрэг тоглуулахыг хүссэн бүх зүйлээ сонсох боломжтой хэвээр байна."</string> <string name="zen_alarms_introduction" msgid="3987266042682300470">"Танд сэрүүлгээс бусад дуу, чичиргээ саад болохгүй. Та хөгжим, видео, тоглоом зэрэг тоглуулахыг хүссэн бүх зүйлээ сонсох боломжтой хэвээр байна."</string> @@ -471,6 +478,8 @@ <string name="keyguard_indication_charging_time_slowly" msgid="301936949731705417">"<xliff:g id="PERCENTAGE">%2$s</xliff:g> • Удаан цэнэглэж байна • <xliff:g id="CHARGING_TIME_LEFT">%1$s</xliff:g>-н дараа дүүрнэ"</string> <string name="keyguard_indication_charging_time_dock" msgid="3149328898931741271">"<xliff:g id="PERCENTAGE">%2$s</xliff:g> • Цэнэглэж байна • <xliff:g id="CHARGING_TIME_LEFT">%1$s</xliff:g>-н дараа дүүрнэ"</string> <string name="accessibility_action_open_communal_hub" msgid="3081702792413787849">"Түгжээтэй дэлгэц дээрх виджетүүд"</string> + <!-- no translation found for accessibility_announcement_communal_widget_added (6911593106099328271) --> + <skip /> <string name="communal_tutorial_indicator_text" msgid="4503010353591430123">"Нийтийн практик хичээлийг эхлүүлэхийн тулд зүүн тийш шударна уу"</string> <string name="cta_tile_button_to_open_widget_editor" msgid="3871562362382963878">"Өөрчлөх"</string> <string name="cta_tile_button_to_dismiss" msgid="3377597875997861754">"Хаах"</string> @@ -499,8 +508,7 @@ <string name="accessibility_action_label_place_widget" msgid="1914197458644168978">"сонгосон виджетийг байрлуулах"</string> <string name="communal_widget_picker_title" msgid="1953369090475731663">"Түгжээтэй дэлгэцийн виджет"</string> <string name="communal_widget_picker_description" msgid="490515450110487871">"Таны таблет түгжээтэй байсан ч түгжээтэй дэлгэцийн виджетийг тань дурын хүн үзнэ"</string> - <!-- no translation found for accessibility_action_label_unselect_widget (1041811747619468698) --> - <skip /> + <string name="accessibility_action_label_unselect_widget" msgid="1041811747619468698">"виджетийн сонголтыг болиулах"</string> <string name="communal_widgets_disclaimer_title" msgid="1150954395585308868">"Түгжээтэй дэлгэцийн виджет"</string> <string name="communal_widgets_disclaimer_text" msgid="1423545475160506349">"Виджет ашиглан аппыг нээхийн тулд та өөрийгөө мөн болохыг баталгаажуулах шаардлагатай болно. Мөн таны таблет түгжээтэй байсан ч тэдгээрийг дурын хүн үзэж болохыг санаарай. Зарим виджет таны түгжээтэй дэлгэцэд зориулагдаагүй байж магадгүй ба энд нэмэхэд аюултай байж болзошгүй."</string> <string name="communal_widgets_disclaimer_button" msgid="4423059765740780753">"Ойлголоо"</string> @@ -557,10 +565,8 @@ <string name="media_projection_action_text" msgid="3634906766918186440">"Одоо эхлүүлэх"</string> <string name="empty_shade_text" msgid="8935967157319717412">"Мэдэгдэл байхгүй"</string> <string name="no_unseen_notif_text" msgid="395512586119868682">"Шинэ мэдэгдэл алга"</string> - <!-- no translation found for adaptive_notification_edu_hun_title (7790738150177329960) --> - <skip /> - <!-- no translation found for adaptive_notification_edu_hun_text (7743367744129536610) --> - <skip /> + <string name="adaptive_notification_edu_hun_title" msgid="7790738150177329960">"Мэдэгдлийн хөргөлт асаалттай байна"</string> + <string name="adaptive_notification_edu_hun_text" msgid="7743367744129536610">"Таныг хэт олон мэдэгдэл нэг дор авахад таны төхөөрөмжийн дууны түвшин болон сэрэмжлүүлэг/дохиог 2 хүртэлх минутын турш автоматаар багасгадаг."</string> <string name="go_to_adaptive_notification_settings" msgid="2423690125178298479">"Унтраах"</string> <string name="unlock_to_see_notif_text" msgid="7439033907167561227">"Хуучин мэдэгдлийг харах бол түгжээг тайл"</string> <string name="quick_settings_disclosure_parental_controls" msgid="2114102871438223600">"Энэ төхөөрөмжийг таны эцэг эх удирддаг"</string> @@ -1226,7 +1232,6 @@ <string name="accessibility_fingerprint_bouncer" msgid="7189102492498735519">"Баталгаажуулалт шаардлагатай. Баталгаажуулахын тулд хурууны хээ мэдрэгчид хүрнэ үү."</string> <string name="ongoing_phone_call_content_description" msgid="5332334388483099947">"Үргэлжилж буй утасны дуудлага"</string> <string name="mobile_data_settings_title" msgid="3955246641380064901">"Мобайл дата"</string> - <string name="preference_summary_default_combination" msgid="8453246369903749670">"<xliff:g id="STATE">%1$s</xliff:g> / <xliff:g id="NETWORKMODE">%2$s</xliff:g>"</string> <string name="mobile_data_connection_active" msgid="944490013299018227">"Холбогдсон"</string> <string name="mobile_data_temp_connection_active" msgid="4590222725908806824">"Түр зуур холбогдсон"</string> <string name="mobile_data_poor_connection" msgid="819617772268371434">"Холболт сул байна"</string> @@ -1380,7 +1385,10 @@ <string name="touchpad_tutorial_done_button" msgid="176168488821755503">"Болсон"</string> <string name="touchpad_tutorial_gesture_done" msgid="4784438360736821255">"Үнэхээр сайн ажиллалаа!"</string> <string name="touchpad_back_gesture_action_title" msgid="7199067250654332735">"Буцах"</string> - <string name="touchpad_back_gesture_guidance" msgid="4222430588599527272">"Буцаж очихын тулд мэдрэгч самбар дээр гурван хуруугаараа хүссэн газраа зүүн эсвэл баруун тийш шударна уу."</string> + <!-- no translation found for touchpad_back_gesture_guidance (6263750214998421587) --> + <skip /> + <!-- no translation found for touchpad_back_gesture_finished (5353616006999726249) --> + <skip /> <string name="touchpad_back_gesture_animation_content_description" msgid="2646107450922379918">"Гурван хуруу баруун болон зүүн тийш хөдөлж буйг харуулсан мэдрэгч самбар"</string> <string name="touchpad_back_gesture_screen_animation_content_description" msgid="4036267494237748710">"Буцах зангаанд зориулсан анимацийг харуулсан төхөөрөмжийн дэлгэц"</string> <string name="keyboard_backlight_dialog_title" msgid="8273102932345564724">"Гарын арын гэрэл"</string> @@ -1388,28 +1396,16 @@ <string name="home_controls_dream_label" msgid="6567105701292324257">"Гэрийн удирдлага"</string> <string name="home_controls_dream_description" msgid="4644150952104035789">"Гэрийн удирдлагадаа дэлгэц амраагчаар шуурхай ханд"</string> <string name="volume_undo_action" msgid="5815519725211877114">"Болих"</string> - <!-- no translation found for back_edu_toast_content (4530314597378982956) --> - <skip /> - <!-- no translation found for home_edu_toast_content (3381071147871955415) --> - <skip /> - <!-- no translation found for overview_edu_toast_content (5797030644017804518) --> - <skip /> - <!-- no translation found for all_apps_edu_toast_content (8807496014667211562) --> - <skip /> - <!-- no translation found for back_edu_notification_title (5624780717751357278) --> - <skip /> - <!-- no translation found for back_edu_notification_content (2497557451540954068) --> - <skip /> - <!-- no translation found for home_edu_notification_title (6097902076909654045) --> - <skip /> - <!-- no translation found for home_edu_notification_content (6631697734535766588) --> - <skip /> - <!-- no translation found for overview_edu_notification_title (1265824157319562406) --> - <skip /> - <!-- no translation found for overview_edu_notification_content (3578204677648432500) --> - <skip /> - <!-- no translation found for all_apps_edu_notification_title (372262997265569063) --> - <skip /> - <!-- no translation found for all_apps_edu_notification_content (3255070575694025585) --> - <skip /> + <string name="back_edu_toast_content" msgid="4530314597378982956">"Буцахын тулд мэдрэгч самбар дээр гурван хуруугаараа зүүн эсвэл баруун тийш шударна уу"</string> + <string name="home_edu_toast_content" msgid="3381071147871955415">"Нүүр хуудас руу очихын тулд мэдрэгч самбар дээр гурван хуруугаараа дээш шударна уу"</string> + <string name="overview_edu_toast_content" msgid="5797030644017804518">"Саяхны аппуудыг харахын тулд мэдрэгч самбар дээр гурван хуруугаараа дээш шудраад, удаан дарна уу"</string> + <string name="all_apps_edu_toast_content" msgid="8807496014667211562">"Бүх аппаа харахын тулд гар дээр тань байх тусгай товчлуурыг дарна уу"</string> + <string name="back_edu_notification_title" msgid="5624780717751357278">"Буцахын тулд мэдрэгч самбараа ашиглах"</string> + <string name="back_edu_notification_content" msgid="2497557451540954068">"Гурван хуруугаараа зүүн эсвэл баруун тийш шударна уу. Илүү олон зангаа сурахын тулд товшино уу."</string> + <string name="home_edu_notification_title" msgid="6097902076909654045">"Нүүр хуудас руу очихын тулд мэдрэгч самбараа ашиглах"</string> + <string name="home_edu_notification_content" msgid="6631697734535766588">"Гурван хуруугаа ашиглан дээш шударна уу. Илүү олон зангаа сурахын тулд товшино уу."</string> + <string name="overview_edu_notification_title" msgid="1265824157319562406">"Саяхны аппуудыг харахын тулд мэдрэгч самбараа ашиглах"</string> + <string name="overview_edu_notification_content" msgid="3578204677648432500">"Гурван хуруугаа ашиглан дээш шудраад, удаан дарна уу. Илүү олон зангаа сурахын тулд товшино уу."</string> + <string name="all_apps_edu_notification_title" msgid="372262997265569063">"Бүх аппыг харахын тулд гараа ашиглах"</string> + <string name="all_apps_edu_notification_content" msgid="3255070575694025585">"Тусгай товчлуурыг хүссэн үедээ дарна уу. Илүү олон зангаа сурахын тулд товшино уу."</string> </resources> diff --git a/packages/SystemUI/res/values-mn/tiles_states_strings.xml b/packages/SystemUI/res/values-mn/tiles_states_strings.xml index 5a32c09d152c..a3f54541880d 100644 --- a/packages/SystemUI/res/values-mn/tiles_states_strings.xml +++ b/packages/SystemUI/res/values-mn/tiles_states_strings.xml @@ -56,11 +56,6 @@ <item msgid="5376619709702103243">"Унтраалттай"</item> <item msgid="4875147066469902392">"Асаалттай"</item> </string-array> - <string-array name="tile_states_modes"> - <item msgid="7764936419245199023">"Боломжгүй"</item> - <item msgid="2004750556637773692">"Унтраалттай"</item> - <item msgid="8968530753931637871">"Асаалттай"</item> - </string-array> <string-array name="tile_states_flashlight"> <item msgid="3465257127433353857">"Боломжгүй"</item> <item msgid="5044688398303285224">"Унтраалттай"</item> diff --git a/packages/SystemUI/res/values-mr/strings.xml b/packages/SystemUI/res/values-mr/strings.xml index 245b42f93092..e3510ad7c3c0 100644 --- a/packages/SystemUI/res/values-mr/strings.xml +++ b/packages/SystemUI/res/values-mr/strings.xml @@ -388,6 +388,9 @@ <string name="performance" msgid="6552785217174378320">"परफॉर्मन्स"</string> <string name="user_interface" msgid="3712869377953950887">"यूझर इंटरफेस"</string> <string name="thermal" msgid="6758074791325414831">"थर्मल"</string> + <string name="custom" msgid="3337456985275158299">"कस्टम"</string> + <string name="custom_trace_settings_dialog_title" msgid="2608570500144830554">"मागाच्या कस्टम सेटिंग्ज"</string> + <string name="restore_default" msgid="5259420807486239755">"डीफॉल्ट रिस्टोअर करा"</string> <string name="quick_settings_onehanded_label" msgid="2416537930246274991">"एकहाती मोड"</string> <string name="quick_settings_hearing_devices_label" msgid="7277170419679404129">"श्रवणयंत्रे"</string> <string name="quick_settings_hearing_devices_connected" msgid="6519069502397037781">"ॲक्टिव्ह आहे"</string> @@ -431,6 +434,12 @@ <string name="zen_modes_dialog_settings" msgid="2310248023728936697">"सेटिंग्ज"</string> <string name="zen_mode_on" msgid="9085304934016242591">"सुरू आहे"</string> <string name="zen_mode_off" msgid="1736604456618147306">"बंद आहे"</string> + <!-- no translation found for zen_mode_set_up (7457957033034460064) --> + <skip /> + <!-- no translation found for zen_mode_no_manual_invocation (1769975741344633672) --> + <skip /> + <!-- no translation found for zen_mode_active_modes (1625850411578488856) --> + <skip /> <string name="zen_priority_introduction" msgid="3159291973383796646">"अलार्म, रिमाइंडर, इव्हेंट आणि तुम्ही निश्चित केलेल्या कॉलर व्यतिरिक्त तुम्हाला कोणत्याही आवाज आणि कंपनांचा व्यत्त्यय आणला जाणार नाही. तरीही तुम्ही प्ले करायचे ठरवलेले कोणतेही संगीत, व्हिडिओ आणि गेमचे आवाज ऐकू शकतात."</string> <string name="zen_alarms_introduction" msgid="3987266042682300470">"अलार्म व्यतिरिक्त तुम्हाला कोणत्याही आवाज आणि कंपनांचा व्यत्त्यय आणला जाणार नाही. तरीही तुम्ही प्ले करायचे ठरवलेले कोणतेही संगीत, व्हिडिओ आणि गेमचे आवाज ऐकू शकतात."</string> <string name="zen_priority_customize_button" msgid="4119213187257195047">"सानुकूलित करा"</string> @@ -469,6 +478,8 @@ <string name="keyguard_indication_charging_time_slowly" msgid="301936949731705417">"<xliff:g id="PERCENTAGE">%2$s</xliff:g> • हळू चार्ज होत आहे • <xliff:g id="CHARGING_TIME_LEFT">%1$s</xliff:g> मध्ये पूर्ण होईल"</string> <string name="keyguard_indication_charging_time_dock" msgid="3149328898931741271">"<xliff:g id="PERCENTAGE">%2$s</xliff:g> • चार्ज होत आहे • <xliff:g id="CHARGING_TIME_LEFT">%1$s</xliff:g> मध्ये पूर्ण होईल"</string> <string name="accessibility_action_open_communal_hub" msgid="3081702792413787849">"लॉक स्क्रीनवरील विजेट"</string> + <!-- no translation found for accessibility_announcement_communal_widget_added (6911593106099328271) --> + <skip /> <string name="communal_tutorial_indicator_text" msgid="4503010353591430123">"सामुदायिक ट्यूटोरियल सुरू करण्यासाठी डावीकडे स्वाइप करा"</string> <string name="cta_tile_button_to_open_widget_editor" msgid="3871562362382963878">"कस्टमाइझ करा"</string> <string name="cta_tile_button_to_dismiss" msgid="3377597875997861754">"डिसमिस करा"</string> @@ -554,10 +565,8 @@ <string name="media_projection_action_text" msgid="3634906766918186440">"आता सुरू करा"</string> <string name="empty_shade_text" msgid="8935967157319717412">"सूचना नाहीत"</string> <string name="no_unseen_notif_text" msgid="395512586119868682">"नवीन सूचना नाहीत"</string> - <!-- no translation found for adaptive_notification_edu_hun_title (7790738150177329960) --> - <skip /> - <!-- no translation found for adaptive_notification_edu_hun_text (7743367744129536610) --> - <skip /> + <string name="adaptive_notification_edu_hun_title" msgid="7790738150177329960">"नोटिफिकेशन कूलडाउन सुरू आहे"</string> + <string name="adaptive_notification_edu_hun_text" msgid="7743367744129536610">"एकाच वेळी अनेक नोटिफिकेशन मिळाल्यास, डिव्हाइसचा आवाज आणि सूचना आपोआप कमाल २ मिनिटांपर्यंत कमी होतात."</string> <string name="go_to_adaptive_notification_settings" msgid="2423690125178298479">"बंद करा"</string> <string name="unlock_to_see_notif_text" msgid="7439033907167561227">"जुन्या सूचना पाहण्यासाठी अनलॉक करा"</string> <string name="quick_settings_disclosure_parental_controls" msgid="2114102871438223600">"हे डिव्हाइस तुमच्या पालकाने व्यवस्थापित केले आहे"</string> @@ -1223,7 +1232,6 @@ <string name="accessibility_fingerprint_bouncer" msgid="7189102492498735519">"ऑथेंटिकेशन आवश्यक आहे. ऑथेंटिकेट करण्यासाठी फिंगरप्रिंट सेन्सरला स्पर्श करा."</string> <string name="ongoing_phone_call_content_description" msgid="5332334388483099947">"फोन कॉल सुरू आहे"</string> <string name="mobile_data_settings_title" msgid="3955246641380064901">"मोबाइल डेटा"</string> - <string name="preference_summary_default_combination" msgid="8453246369903749670">"<xliff:g id="STATE">%1$s</xliff:g> / <xliff:g id="NETWORKMODE">%2$s</xliff:g>"</string> <string name="mobile_data_connection_active" msgid="944490013299018227">"कनेक्ट केले आहे"</string> <string name="mobile_data_temp_connection_active" msgid="4590222725908806824">"तात्पुरते कनेक्ट केलेले"</string> <string name="mobile_data_poor_connection" msgid="819617772268371434">"खराब कनेक्शन"</string> @@ -1377,7 +1385,10 @@ <string name="touchpad_tutorial_done_button" msgid="176168488821755503">"पूर्ण झाले"</string> <string name="touchpad_tutorial_gesture_done" msgid="4784438360736821255">"उत्तम कामगिरी!"</string> <string name="touchpad_back_gesture_action_title" msgid="7199067250654332735">"मागे जा"</string> - <string name="touchpad_back_gesture_guidance" msgid="4222430588599527272">"मागे जाण्यासाठी, टचपॅडवर कुठेही तीन बोटांनी डावीकडे किंवा उजवीकडे स्वाइप करा."</string> + <!-- no translation found for touchpad_back_gesture_guidance (6263750214998421587) --> + <skip /> + <!-- no translation found for touchpad_back_gesture_finished (5353616006999726249) --> + <skip /> <string name="touchpad_back_gesture_animation_content_description" msgid="2646107450922379918">"तीन बोट उजवीकडे आणि डावीकडे हलताना दाखवणारे टचपॅड"</string> <string name="touchpad_back_gesture_screen_animation_content_description" msgid="4036267494237748710">"मागील जेश्चरसाठी अॅनिमेशन दाखवणारी डिव्हाइस स्क्रीन"</string> <string name="keyboard_backlight_dialog_title" msgid="8273102932345564724">"कीबोर्ड बॅकलाइट"</string> diff --git a/packages/SystemUI/res/values-mr/tiles_states_strings.xml b/packages/SystemUI/res/values-mr/tiles_states_strings.xml index fdb1f40b4803..54c320c953d5 100644 --- a/packages/SystemUI/res/values-mr/tiles_states_strings.xml +++ b/packages/SystemUI/res/values-mr/tiles_states_strings.xml @@ -56,11 +56,6 @@ <item msgid="5376619709702103243">"बंद आहे"</item> <item msgid="4875147066469902392">"सुरू आहे"</item> </string-array> - <string-array name="tile_states_modes"> - <item msgid="7764936419245199023">"उपलब्ध नाही"</item> - <item msgid="2004750556637773692">"बंद आहे"</item> - <item msgid="8968530753931637871">"सुरू आहे"</item> - </string-array> <string-array name="tile_states_flashlight"> <item msgid="3465257127433353857">"उपलब्ध नाही"</item> <item msgid="5044688398303285224">"बंद आहे"</item> diff --git a/packages/SystemUI/res/values-ms/strings.xml b/packages/SystemUI/res/values-ms/strings.xml index bca52729118f..0e91cb467071 100644 --- a/packages/SystemUI/res/values-ms/strings.xml +++ b/packages/SystemUI/res/values-ms/strings.xml @@ -388,6 +388,9 @@ <string name="performance" msgid="6552785217174378320">"Prestasi"</string> <string name="user_interface" msgid="3712869377953950887">"Antara Muka Pengguna"</string> <string name="thermal" msgid="6758074791325414831">"Terma"</string> + <string name="custom" msgid="3337456985275158299">"Tersuai"</string> + <string name="custom_trace_settings_dialog_title" msgid="2608570500144830554">"Tetapan Surih Tersuai"</string> + <string name="restore_default" msgid="5259420807486239755">"Pemulihan Lalai"</string> <string name="quick_settings_onehanded_label" msgid="2416537930246274991">"Mod sebelah tangan"</string> <string name="quick_settings_hearing_devices_label" msgid="7277170419679404129">"Peranti pendengaran"</string> <string name="quick_settings_hearing_devices_connected" msgid="6519069502397037781">"Aktif"</string> @@ -431,6 +434,9 @@ <string name="zen_modes_dialog_settings" msgid="2310248023728936697">"Tetapan"</string> <string name="zen_mode_on" msgid="9085304934016242591">"Hidup"</string> <string name="zen_mode_off" msgid="1736604456618147306">"Mati"</string> + <string name="zen_mode_set_up" msgid="7457957033034460064">"Sediakan"</string> + <string name="zen_mode_no_manual_invocation" msgid="1769975741344633672">"Urus dalam tetapan"</string> + <string name="zen_mode_active_modes" msgid="1625850411578488856">"{count,plural, =0{Tiada mod yang aktif}=1{{mode} aktif}other{# mod aktif}}"</string> <string name="zen_priority_introduction" msgid="3159291973383796646">"Anda tidak akan diganggu oleh bunyi dan getaran, kecuali daripada penggera, peringatan, acara dan pemanggil yang anda tetapkan. Anda masih mendengar item lain yang anda pilih untuk dimainkan termasuk muzik, video dan permainan."</string> <string name="zen_alarms_introduction" msgid="3987266042682300470">"Anda tidak akan diganggu oleh bunyi dan getaran, kecuali daripada penggera. Anda masih mendengar item lain yang anda pilih untuk dimainkan termasuk muzik, video dan permainan."</string> <string name="zen_priority_customize_button" msgid="4119213187257195047">"Peribadikan"</string> @@ -469,6 +475,8 @@ <string name="keyguard_indication_charging_time_slowly" msgid="301936949731705417">"<xliff:g id="PERCENTAGE">%2$s</xliff:g> • Mengecas dengan perlahan • Penuh dalam masa <xliff:g id="CHARGING_TIME_LEFT">%1$s</xliff:g>"</string> <string name="keyguard_indication_charging_time_dock" msgid="3149328898931741271">"<xliff:g id="PERCENTAGE">%2$s</xliff:g> • Mengecas • Penuh dalam masa <xliff:g id="CHARGING_TIME_LEFT">%1$s</xliff:g>"</string> <string name="accessibility_action_open_communal_hub" msgid="3081702792413787849">"Widget pada skrin kunci"</string> + <!-- no translation found for accessibility_announcement_communal_widget_added (6911593106099328271) --> + <skip /> <string name="communal_tutorial_indicator_text" msgid="4503010353591430123">"Leret ke kiri untuk memulakan tutorial umum"</string> <string name="cta_tile_button_to_open_widget_editor" msgid="3871562362382963878">"Sesuaikan"</string> <string name="cta_tile_button_to_dismiss" msgid="3377597875997861754">"Ketepikan"</string> @@ -554,10 +562,8 @@ <string name="media_projection_action_text" msgid="3634906766918186440">"Mulakan sekarang"</string> <string name="empty_shade_text" msgid="8935967157319717412">"Tiada pemberitahuan"</string> <string name="no_unseen_notif_text" msgid="395512586119868682">"Tiada pemberitahuan baharu"</string> - <!-- no translation found for adaptive_notification_edu_hun_title (7790738150177329960) --> - <skip /> - <!-- no translation found for adaptive_notification_edu_hun_text (7743367744129536610) --> - <skip /> + <string name="adaptive_notification_edu_hun_title" msgid="7790738150177329960">"Tempoh bertenang pemberitahuan dihidupkan"</string> + <string name="adaptive_notification_edu_hun_text" msgid="7743367744129536610">"Kelantangan, makluman peranti dikurangkan secara automatik hingga 2 minit apabila menerima banyak pemberitahuan serentak."</string> <string name="go_to_adaptive_notification_settings" msgid="2423690125178298479">"Matikan"</string> <string name="unlock_to_see_notif_text" msgid="7439033907167561227">"Buka kunci untuk melihat pemberitahuan lama"</string> <string name="quick_settings_disclosure_parental_controls" msgid="2114102871438223600">"Peranti ini diurus oleh ibu bapa anda"</string> @@ -1223,7 +1229,6 @@ <string name="accessibility_fingerprint_bouncer" msgid="7189102492498735519">"Pengesahan diperlukan. Sentuh penderia cap jari untuk pengesahan."</string> <string name="ongoing_phone_call_content_description" msgid="5332334388483099947">"Panggilan telefon yang sedang berjalan"</string> <string name="mobile_data_settings_title" msgid="3955246641380064901">"Data mudah alih"</string> - <string name="preference_summary_default_combination" msgid="8453246369903749670">"<xliff:g id="STATE">%1$s</xliff:g> / <xliff:g id="NETWORKMODE">%2$s</xliff:g>"</string> <string name="mobile_data_connection_active" msgid="944490013299018227">"Disambungkan"</string> <string name="mobile_data_temp_connection_active" msgid="4590222725908806824">"Disambungkan buat sementara waktu"</string> <string name="mobile_data_poor_connection" msgid="819617772268371434">"Sambungan lemah"</string> @@ -1377,7 +1382,10 @@ <string name="touchpad_tutorial_done_button" msgid="176168488821755503">"Selesai"</string> <string name="touchpad_tutorial_gesture_done" msgid="4784438360736821255">"Syabas!"</string> <string name="touchpad_back_gesture_action_title" msgid="7199067250654332735">"Kembali"</string> - <string name="touchpad_back_gesture_guidance" msgid="4222430588599527272">"Untuk kembali, leret ke kiri atau kanan menggunakan tiga jari di mana-mana sahaja pada pad sentuh."</string> + <!-- no translation found for touchpad_back_gesture_guidance (6263750214998421587) --> + <skip /> + <!-- no translation found for touchpad_back_gesture_finished (5353616006999726249) --> + <skip /> <string name="touchpad_back_gesture_animation_content_description" msgid="2646107450922379918">"Pad sentuh menunjukkan tiga jari bergerak ke kanan dan kiri"</string> <string name="touchpad_back_gesture_screen_animation_content_description" msgid="4036267494237748710">"Skrin peranti menunjukkan animasi untuk gerak isyarat kembali"</string> <string name="keyboard_backlight_dialog_title" msgid="8273102932345564724">"Cahaya latar papan kekunci"</string> diff --git a/packages/SystemUI/res/values-ms/tiles_states_strings.xml b/packages/SystemUI/res/values-ms/tiles_states_strings.xml index db63e2c03e9e..174e416e3508 100644 --- a/packages/SystemUI/res/values-ms/tiles_states_strings.xml +++ b/packages/SystemUI/res/values-ms/tiles_states_strings.xml @@ -56,11 +56,6 @@ <item msgid="5376619709702103243">"Mati"</item> <item msgid="4875147066469902392">"Hidup"</item> </string-array> - <string-array name="tile_states_modes"> - <item msgid="7764936419245199023">"Tidak tersedia"</item> - <item msgid="2004750556637773692">"Mati"</item> - <item msgid="8968530753931637871">"Hidup"</item> - </string-array> <string-array name="tile_states_flashlight"> <item msgid="3465257127433353857">"Tidak tersedia"</item> <item msgid="5044688398303285224">"Mati"</item> diff --git a/packages/SystemUI/res/values-my/strings.xml b/packages/SystemUI/res/values-my/strings.xml index c21b11262a27..d7b20ef089ce 100644 --- a/packages/SystemUI/res/values-my/strings.xml +++ b/packages/SystemUI/res/values-my/strings.xml @@ -127,24 +127,24 @@ <string name="screenrecord_save_error" msgid="5862648532560118815">"ဖန်သားပြင်ရိုက်ကူးမှုကို သိမ်းရာတွင် အမှားရှိသည်"</string> <string name="screenrecord_start_error" msgid="2200660692479682368">"ဖန်သားပြင် ရိုက်ကူးမှု စတင်ရာတွင် အမှားအယွင်းရှိနေသည်"</string> <string name="screenrecord_stop_dialog_title" msgid="8716193661764511095">"ရိုက်ကူးခြင်း ရပ်မလား။"</string> - <string name="screenrecord_stop_dialog_message" msgid="6262768207331626817">"လောလောဆယ် ဖန်သားပြင်တစ်ခုလုံးကို ရိုက်ကူးနေသည်"</string> - <string name="screenrecord_stop_dialog_message_specific_app" msgid="5995770227684523244">"လောလောဆယ် <xliff:g id="APP_NAME">%1$s</xliff:g> ကို ရိုက်ကူးနေသည်"</string> + <string name="screenrecord_stop_dialog_message" msgid="6262768207331626817">"သင်သည် လက်ရှိတွင် ဖန်သားပြင်တစ်ခုလုံးကို ရိုက်ကူးနေသည်"</string> + <string name="screenrecord_stop_dialog_message_specific_app" msgid="5995770227684523244">"သင်သည် လက်ရှိတွင် <xliff:g id="APP_NAME">%1$s</xliff:g> ကို ရိုက်ကူးနေသည်"</string> <string name="screenrecord_stop_dialog_button" msgid="2883812564938194350">"ရိုက်ကူးမှု ရပ်ရန်"</string> <string name="share_to_app_chip_accessibility_label" msgid="4210256229976947065">"ဖန်သားပြင်ကို မျှဝေနေသည်"</string> <string name="share_to_app_stop_dialog_title" msgid="9212915050910250438">"ဖန်သားပြင်မျှဝေခြင်း ရပ်မလား။"</string> - <string name="share_to_app_stop_dialog_message_entire_screen_with_host_app" msgid="522823522115375414">"<xliff:g id="HOST_APP_NAME">%1$s</xliff:g> ဖြင့် သင့်ဖန်သားပြင်တစ်ခုလုံးကို လောလောဆယ် မျှဝေနေသည်"</string> - <string name="share_to_app_stop_dialog_message_entire_screen" msgid="5090115386271179270">"အက်ပ်ဖြင့် သင့်ဖန်သားပြင်တစ်ခုလုံးကို လောလောဆယ် မျှဝေနေသည်"</string> - <string name="share_to_app_stop_dialog_message_single_app_specific" msgid="5923772039347985172">"<xliff:g id="APP_BEING_SHARED_NAME">%1$s</xliff:g> ကို လောလောဆယ် မျှဝေနေသည်"</string> - <string name="share_to_app_stop_dialog_message_single_app_generic" msgid="6681016774654578261">"အက်ပ်ကို လောလောဆယ် မျှဝေနေသည်"</string> + <string name="share_to_app_stop_dialog_message_entire_screen_with_host_app" msgid="522823522115375414">"သင်သည် လက်ရှိတွင် <xliff:g id="HOST_APP_NAME">%1$s</xliff:g> ဖြင့် ဖန်သားပြင်တစ်ခုလုံးကို မျှဝေနေသည်"</string> + <string name="share_to_app_stop_dialog_message_entire_screen" msgid="5090115386271179270">"သင်သည် လက်ရှိတွင် အက်ပ်တစ်ခုဖြင့် ဖန်သားပြင်တစ်ခုလုံးကို မျှဝေနေသည်"</string> + <string name="share_to_app_stop_dialog_message_single_app_specific" msgid="5923772039347985172">"သင်သည် လက်ရှိတွင် <xliff:g id="APP_BEING_SHARED_NAME">%1$s</xliff:g> ကို မျှဝေနေသည်"</string> + <string name="share_to_app_stop_dialog_message_single_app_generic" msgid="6681016774654578261">"သင်သည် လက်ရှိတွင် အက်ပ်ကို မျှဝေနေသည်"</string> <string name="share_to_app_stop_dialog_button" msgid="6334056916284230217">"မျှဝေခြင်း ရပ်ရန်"</string> <string name="cast_screen_to_other_device_chip_accessibility_label" msgid="4687917476203009885">"ဖန်သားပြင်ကို ကာစ်လုပ်နေသည်"</string> <string name="cast_to_other_device_stop_dialog_title" msgid="7836517190930357326">"ကာစ်လုပ်ခြင်းကို ရပ်လိုသလား။"</string> - <string name="cast_to_other_device_stop_dialog_message_entire_screen_with_device" msgid="1474703115926205251">"သင့်ဖန်သားပြင်တစ်ခုလုံးကို <xliff:g id="DEVICE_NAME">%1$s</xliff:g> သို့ လောလောဆယ် ကာစ်လုပ်နေသည်"</string> - <string name="cast_to_other_device_stop_dialog_message_entire_screen" msgid="8419219169553867625">"သင့်ဖန်သားပြင်တစ်ခုလုံးကို အနီးတစ်ဝိုက်ရှိ စက်သို့ လောလောဆယ် ကာစ်လုပ်နေသည်"</string> - <string name="cast_to_other_device_stop_dialog_message_specific_app_with_device" msgid="2715934698604085519">"<xliff:g id="APP_BEING_SHARED_NAME">%1$s</xliff:g> ကို <xliff:g id="DEVICE_NAME">%2$s</xliff:g> သို့ လောလောဆယ် ကာစ်လုပ်နေသည်"</string> - <string name="cast_to_other_device_stop_dialog_message_specific_app" msgid="8616103075630934513">"<xliff:g id="APP_BEING_SHARED_NAME">%1$s</xliff:g> ကို အနီးတစ်ဝိုက်ရှိ စက်သို့ လောလောဆယ် ကာစ်လုပ်နေသည်"</string> - <string name="cast_to_other_device_stop_dialog_message_generic_with_device" msgid="9213582497852420203">"<xliff:g id="DEVICE_NAME">%1$s</xliff:g> သို့ လောလောဆယ် ကာစ်လုပ်နေသည်"</string> - <string name="cast_to_other_device_stop_dialog_message_generic" msgid="4100272100480415076">"အနီးတစ်ဝိုက်ရှိ စက်သို့ လောလောဆယ် ကာစ်လုပ်နေသည်"</string> + <string name="cast_to_other_device_stop_dialog_message_entire_screen_with_device" msgid="1474703115926205251">"သင်သည် လက်ရှိတွင် ဖန်သားပြင်တစ်ခုလုံးကို <xliff:g id="DEVICE_NAME">%1$s</xliff:g> သို့ ကာစ်လုပ်နေသည်"</string> + <string name="cast_to_other_device_stop_dialog_message_entire_screen" msgid="8419219169553867625">"သင်သည် လက်ရှိတွင် ဖန်သားပြင်တစ်ခုလုံးကို အနီးတစ်ဝိုက်ရှိ စက်သို့ ကာစ်လုပ်နေသည်"</string> + <string name="cast_to_other_device_stop_dialog_message_specific_app_with_device" msgid="2715934698604085519">"သင်သည် လက်ရှိတွင် <xliff:g id="APP_BEING_SHARED_NAME">%1$s</xliff:g> ကို <xliff:g id="DEVICE_NAME">%2$s</xliff:g> သို့ ကာစ်လုပ်နေသည်"</string> + <string name="cast_to_other_device_stop_dialog_message_specific_app" msgid="8616103075630934513">"သင်သည် လက်ရှိတွင် <xliff:g id="APP_BEING_SHARED_NAME">%1$s</xliff:g> ကို အနီးတစ်ဝိုက်ရှိ စက်သို့ ကာစ်လုပ်နေသည်"</string> + <string name="cast_to_other_device_stop_dialog_message_generic_with_device" msgid="9213582497852420203">"သင်သည် လက်ရှိတွင် <xliff:g id="DEVICE_NAME">%1$s</xliff:g> သို့ ကာစ်လုပ်နေသည်"</string> + <string name="cast_to_other_device_stop_dialog_message_generic" msgid="4100272100480415076">"သင်သည် လက်ရှိတွင် အနီးတစ်ဝိုက်ရှိ စက်သို့ ကာစ်လုပ်နေသည်"</string> <string name="cast_to_other_device_stop_dialog_button" msgid="6420183747435521834">"ကာစ် ရပ်ရန်"</string> <string name="close_dialog_button" msgid="4749497706540104133">"ပိတ်ရန်"</string> <string name="issuerecord_title" msgid="286627115110121849">"ပြဿနာရိုက်ကူးစနစ်"</string> @@ -388,6 +388,9 @@ <string name="performance" msgid="6552785217174378320">"စွမ်းဆောင်ရည်"</string> <string name="user_interface" msgid="3712869377953950887">"သုံးသူအတွက် ကြားခံစနစ်"</string> <string name="thermal" msgid="6758074791325414831">"အပူဓာတ်"</string> + <string name="custom" msgid="3337456985275158299">"စိတ်ကြိုက်"</string> + <string name="custom_trace_settings_dialog_title" msgid="2608570500144830554">"စိတ်ကြိုက်လုပ်ဆောင်ချက်မှတ်တမ်း ဆက်တင်များ"</string> + <string name="restore_default" msgid="5259420807486239755">"မူရင်းအတိုင်း ပြန်ပြောင်းရန်"</string> <string name="quick_settings_onehanded_label" msgid="2416537930246274991">"လက်တစ်ဖက်သုံးမုဒ်"</string> <string name="quick_settings_hearing_devices_label" msgid="7277170419679404129">"နားကြားကိရိယာ"</string> <string name="quick_settings_hearing_devices_connected" msgid="6519069502397037781">"သုံးနေသည်"</string> @@ -429,10 +432,11 @@ <string name="zen_modes_dialog_title" msgid="4159138230418567383">"ဦးစားပေးမုဒ်"</string> <string name="zen_modes_dialog_done" msgid="6654130880256438950">"ပြီးပြီ"</string> <string name="zen_modes_dialog_settings" msgid="2310248023728936697">"ဆက်တင်များ"</string> - <!-- no translation found for zen_mode_on (9085304934016242591) --> - <skip /> - <!-- no translation found for zen_mode_off (1736604456618147306) --> - <skip /> + <string name="zen_mode_on" msgid="9085304934016242591">"ဖွင့်"</string> + <string name="zen_mode_off" msgid="1736604456618147306">"ပိတ်"</string> + <string name="zen_mode_set_up" msgid="7457957033034460064">"စနစ်ထည့်သွင်းရန်"</string> + <string name="zen_mode_no_manual_invocation" msgid="1769975741344633672">"ဆက်တင်များတွင် စီမံရန်"</string> + <string name="zen_mode_active_modes" msgid="1625850411578488856">"{count,plural, =0{အသုံးပြုနေသော မုဒ်မရှိပါ}=1{{mode} ကို အသုံးပြုနေသည်}other{မုဒ် # ခုကို အသုံးပြုနေသည်}}"</string> <string name="zen_priority_introduction" msgid="3159291973383796646">"နှိုးစက်သံ၊ သတိပေးချက်အသံများ၊ ပွဲစဉ်သတိပေးသံများနှင့် သင်ခွင့်ပြုထားသူများထံမှ ဖုန်းခေါ်မှုများမှလွဲ၍ အခြားအသံများနှင့် တုန်ခါမှုများက သင့်ကို အနှောင့်အယှက်ပြုမည် မဟုတ်ပါ။ သို့သော်လည်း သီချင်း၊ ဗီဒီယိုနှင့် ဂိမ်းများအပါအဝင် သင်ကရွေးချယ်ဖွင့်ထားသည့် အရာတိုင်း၏ အသံကိုမူ ကြားနေရဆဲဖြစ်ပါလိမ့်မည်။"</string> <string name="zen_alarms_introduction" msgid="3987266042682300470">"နှိုးစက်သံမှလွဲ၍ အခြားအသံများနှင့် တုန်ခါမှုများက သင့်ကို အနှောင့်အယှက်ပြုမည် မဟုတ်ပါ။ သို့သော်လည်း သီချင်း၊ ဗီဒီယိုနှင့် ဂိမ်းများအပါအဝင် သင်ကရွေးချယ်ဖွင့်ထားသည့် အရာတိုင်း၏ အသံကိုမူ ကြားနေရဆဲဖြစ်ပါလိမ့်မည်။"</string> <string name="zen_priority_customize_button" msgid="4119213187257195047">"စိတ်ကြိုက် ပြုလုပ်ရန်"</string> @@ -471,6 +475,8 @@ <string name="keyguard_indication_charging_time_slowly" msgid="301936949731705417">"<xliff:g id="PERCENTAGE">%2$s</xliff:g> • နှေးကွေးစွာ အားသွင်းနေသည် • အားပြည့်ရန် <xliff:g id="CHARGING_TIME_LEFT">%1$s</xliff:g> လိုသည်"</string> <string name="keyguard_indication_charging_time_dock" msgid="3149328898931741271">"<xliff:g id="PERCENTAGE">%2$s</xliff:g> • အားသွင်းနေသည် • အားပြည့်ရန် <xliff:g id="CHARGING_TIME_LEFT">%1$s</xliff:g> လိုသည်"</string> <string name="accessibility_action_open_communal_hub" msgid="3081702792413787849">"လော့ခ်မျက်နှာပြင်ရှိ ဝိဂျက်များ"</string> + <!-- no translation found for accessibility_announcement_communal_widget_added (6911593106099328271) --> + <skip /> <string name="communal_tutorial_indicator_text" msgid="4503010353591430123">"အများသုံးရှင်းလင်းပို့ချချက် စတင်ရန် ဘယ်သို့ပွတ်ဆွဲပါ"</string> <string name="cta_tile_button_to_open_widget_editor" msgid="3871562362382963878">"စိတ်ကြိုက်လုပ်ရန်"</string> <string name="cta_tile_button_to_dismiss" msgid="3377597875997861754">"ပယ်ရန်"</string> @@ -499,8 +505,7 @@ <string name="accessibility_action_label_place_widget" msgid="1914197458644168978">"ရွေးချယ်ထားသော ဝိဂျက်ကို တင်ရန်"</string> <string name="communal_widget_picker_title" msgid="1953369090475731663">"လော့ခ်မျက်နှာပြင် ဝိဂျက်များ"</string> <string name="communal_widget_picker_description" msgid="490515450110487871">"တက်ဘလက်လော့ခ်ချထားသော်လည်း မည်သူမဆို လော့ခ်မျက်နှာပြင်ဝိဂျက်ကို ကြည့်နိုင်သည်။"</string> - <!-- no translation found for accessibility_action_label_unselect_widget (1041811747619468698) --> - <skip /> + <string name="accessibility_action_label_unselect_widget" msgid="1041811747619468698">"ဝိဂျက် ပြန်ဖြုတ်ရန်"</string> <string name="communal_widgets_disclaimer_title" msgid="1150954395585308868">"လော့ခ်မျက်နှာပြင် ဝိဂျက်များ"</string> <string name="communal_widgets_disclaimer_text" msgid="1423545475160506349">"ဝိဂျက်သုံး၍ အက်ပ်ဖွင့်ရန်အတွက် သင်ဖြစ်ကြောင်း အတည်ပြုရန်လိုသည်။ ထို့ပြင် သင့်တက်ဘလက် လော့ခ်ချထားချိန်၌ပင် မည်သူမဆို ၎င်းတို့ကို ကြည့်နိုင်ကြောင်း သတိပြုပါ။ ဝိဂျက်အချို့ကို လော့ခ်မျက်နှာပြင်အတွက် ရည်ရွယ်ထားခြင်း မရှိသဖြင့် ဤနေရာတွင် ထည့်ပါက မလုံခြုံနိုင်ပါ။"</string> <string name="communal_widgets_disclaimer_button" msgid="4423059765740780753">"နားလည်ပြီ"</string> @@ -557,10 +562,8 @@ <string name="media_projection_action_text" msgid="3634906766918186440">"ယခု စတင်ပါ"</string> <string name="empty_shade_text" msgid="8935967157319717412">"အကြောင်းကြားချက် မရှိပါ"</string> <string name="no_unseen_notif_text" msgid="395512586119868682">"အကြောင်းကြားချက်သစ် မရှိပါ"</string> - <!-- no translation found for adaptive_notification_edu_hun_title (7790738150177329960) --> - <skip /> - <!-- no translation found for adaptive_notification_edu_hun_text (7743367744129536610) --> - <skip /> + <string name="adaptive_notification_edu_hun_title" msgid="7790738150177329960">"အကြောင်းကြားချက် သတိပေးမှု လျှော့ချခြင်း ဖွင့်ထားသည်"</string> + <string name="adaptive_notification_edu_hun_text" msgid="7743367744129536610">"အကြောင်းကြားချက်များစွာ တစ်ပြိုင်နက်ရပါက သင့်စက်၏ အသံအတိုးအကျယ်နှင့် သတိပေးချက်ကို ၂ မိနစ်ကြာသည်အထိ အလိုအလျောက်လျှော့ချသည်။"</string> <string name="go_to_adaptive_notification_settings" msgid="2423690125178298479">"ပိတ်ရန်"</string> <string name="unlock_to_see_notif_text" msgid="7439033907167561227">"အကြောင်းကြားချက်ဟောင်းကြည့်ရန် လော့ခ်ဖွင့်ပါ"</string> <string name="quick_settings_disclosure_parental_controls" msgid="2114102871438223600">"ဤစက်ပစ္စည်းကို သင့်မိဘက စီမံခန့်ခွဲသည်"</string> @@ -1226,7 +1229,6 @@ <string name="accessibility_fingerprint_bouncer" msgid="7189102492498735519">"အထောက်အထားစိစစ်ခြင်း လိုအပ်သည်။ အထောက်အထားစိစစ်ရန် လက်ဗွေ အာရုံခံကိရိယာကို ထိပါ။"</string> <string name="ongoing_phone_call_content_description" msgid="5332334388483099947">"လက်ရှိ ဖုန်းခေါ်ဆိုမှု"</string> <string name="mobile_data_settings_title" msgid="3955246641380064901">"မိုဘိုင်းဒေတာ"</string> - <string name="preference_summary_default_combination" msgid="8453246369903749670">"<xliff:g id="STATE">%1$s</xliff:g> / <xliff:g id="NETWORKMODE">%2$s</xliff:g>"</string> <string name="mobile_data_connection_active" msgid="944490013299018227">"ချိတ်ဆက်ထားသည်"</string> <string name="mobile_data_temp_connection_active" msgid="4590222725908806824">"ယာယီချိတ်ဆက်ထားသည်"</string> <string name="mobile_data_poor_connection" msgid="819617772268371434">"ချိတ်ဆက်မှုအားနည်းသည်"</string> @@ -1380,7 +1382,10 @@ <string name="touchpad_tutorial_done_button" msgid="176168488821755503">"ပြီးပြီ"</string> <string name="touchpad_tutorial_gesture_done" msgid="4784438360736821255">"တော်ပါပေသည်။"</string> <string name="touchpad_back_gesture_action_title" msgid="7199067250654332735">"ပြန်သွားရန်"</string> - <string name="touchpad_back_gesture_guidance" msgid="4222430588599527272">"ပြန်သွားရန်အတွက် တာ့ချ်ပက်တွင် မည်သည့်နေရာ၌မဆို လက်သုံးချောင်းသုံး၍ ဘယ် (သို့) ညာသို့ ပွတ်ဆွဲပါ။"</string> + <!-- no translation found for touchpad_back_gesture_guidance (6263750214998421587) --> + <skip /> + <!-- no translation found for touchpad_back_gesture_finished (5353616006999726249) --> + <skip /> <string name="touchpad_back_gesture_animation_content_description" msgid="2646107450922379918">"တာ့ချ်ပက်တွင် ဘယ်ညာရွှေ့နေသော လက်သုံးချောင်းကို ပြထားသည်"</string> <string name="touchpad_back_gesture_screen_animation_content_description" msgid="4036267494237748710">"စက်စခရင်တွင် နောက်သို့လက်ဟန်အတွက် လှုပ်ရှားသက်ဝင်ပုံကို ပြထားသည်"</string> <string name="keyboard_backlight_dialog_title" msgid="8273102932345564724">"ကီးဘုတ်နောက်မီး"</string> @@ -1388,28 +1393,16 @@ <string name="home_controls_dream_label" msgid="6567105701292324257">"အိမ်ထိန်းချုပ်မှုများ"</string> <string name="home_controls_dream_description" msgid="4644150952104035789">"အိမ်ထိန်းချုပ်မှုများကို စခရင်နားချိန်ပုံအဖြစ် အမြန်ဝင်ကြည့်ရန်"</string> <string name="volume_undo_action" msgid="5815519725211877114">"နောက်ပြန်ရန်"</string> - <!-- no translation found for back_edu_toast_content (4530314597378982956) --> - <skip /> - <!-- no translation found for home_edu_toast_content (3381071147871955415) --> - <skip /> - <!-- no translation found for overview_edu_toast_content (5797030644017804518) --> - <skip /> - <!-- no translation found for all_apps_edu_toast_content (8807496014667211562) --> - <skip /> - <!-- no translation found for back_edu_notification_title (5624780717751357278) --> - <skip /> - <!-- no translation found for back_edu_notification_content (2497557451540954068) --> - <skip /> - <!-- no translation found for home_edu_notification_title (6097902076909654045) --> - <skip /> - <!-- no translation found for home_edu_notification_content (6631697734535766588) --> - <skip /> - <!-- no translation found for overview_edu_notification_title (1265824157319562406) --> - <skip /> - <!-- no translation found for overview_edu_notification_content (3578204677648432500) --> - <skip /> - <!-- no translation found for all_apps_edu_notification_title (372262997265569063) --> - <skip /> - <!-- no translation found for all_apps_edu_notification_content (3255070575694025585) --> - <skip /> + <string name="back_edu_toast_content" msgid="4530314597378982956">"နောက်ပြန်သွားရန် တာ့ချ်ပက်ပေါ်တွင် လက်သုံးချောင်းဖြင့် ဘယ် (သို့) ညာသို့ ပွတ်ဆွဲပါ"</string> + <string name="home_edu_toast_content" msgid="3381071147871955415">"ပင်မစာမျက်နှာသို့ သွားရန် တာ့ချ်ပက်ပေါ်တွင် လက်သုံးချောင်းဖြင့် အပေါ်သို့ပွတ်ဆွဲပါ"</string> + <string name="overview_edu_toast_content" msgid="5797030644017804518">"လတ်တလောအက်ပ်များကို ကြည့်ရန် တာ့ချ်ပက်ပေါ်တွင် လက်သုံးချောင်းဖြင့် အပေါ်သို့ပွတ်ဆွဲပြီး ဖိထားပါ"</string> + <string name="all_apps_edu_toast_content" msgid="8807496014667211562">"သင့်အက်ပ်အားလုံးကြည့်ရန် ကီးဘုတ်ပေါ်ရှိ လုပ်ဆောင်ချက်ကီးကို နှိပ်ပါ"</string> + <string name="back_edu_notification_title" msgid="5624780717751357278">"နောက်ပြန်သွားရန် သင့်တာ့ချ်ပက်ကို သုံးပါ"</string> + <string name="back_edu_notification_content" msgid="2497557451540954068">"လက်သုံးချောင်းဖြင့် ဘယ် (သို့) ညာသို့ ပွတ်ဆွဲပါ။ လက်ဟန်များ ပိုမိုလေ့လာရန် တို့ပါ။"</string> + <string name="home_edu_notification_title" msgid="6097902076909654045">"ပင်မစာမျက်နှာသို့ သွားရန် သင့်တာ့ချ်ပက်ကို သုံးပါ"</string> + <string name="home_edu_notification_content" msgid="6631697734535766588">"လက်သုံးချောင်းဖြင့် အပေါ်သို့ပွတ်ဆွဲပါ။ လက်ဟန်များ ပိုမိုလေ့လာရန် တို့ပါ။"</string> + <string name="overview_edu_notification_title" msgid="1265824157319562406">"လတ်တလောအက်ပ်များကို ကြည့်ရန် သင့်တာ့ချ်ပက်ကို သုံးပါ"</string> + <string name="overview_edu_notification_content" msgid="3578204677648432500">"လက်သုံးချောင်းဖြင့် အပေါ်သို့ပွတ်ဆွဲပြီး ဖိထားပါ။ လက်ဟန်များ ပိုမိုလေ့လာရန် တို့ပါ။"</string> + <string name="all_apps_edu_notification_title" msgid="372262997265569063">"အက်ပ်အားလုံးကြည့်ရန် သင့်ကီးဘုတ်ကို သုံးပါ"</string> + <string name="all_apps_edu_notification_content" msgid="3255070575694025585">"လုပ်ဆောင်ချက်ကီးကို အချိန်မရွေးနှိပ်ပါ။ လက်ဟန်များ ပိုမိုလေ့လာရန် တို့ပါ။"</string> </resources> diff --git a/packages/SystemUI/res/values-my/tiles_states_strings.xml b/packages/SystemUI/res/values-my/tiles_states_strings.xml index 4e3334faf24e..f665a00a5214 100644 --- a/packages/SystemUI/res/values-my/tiles_states_strings.xml +++ b/packages/SystemUI/res/values-my/tiles_states_strings.xml @@ -56,11 +56,6 @@ <item msgid="5376619709702103243">"ပိတ်"</item> <item msgid="4875147066469902392">"ဖွင့်"</item> </string-array> - <string-array name="tile_states_modes"> - <item msgid="7764936419245199023">"မရနိုင်ပါ"</item> - <item msgid="2004750556637773692">"ပိတ်"</item> - <item msgid="8968530753931637871">"ဖွင့်"</item> - </string-array> <string-array name="tile_states_flashlight"> <item msgid="3465257127433353857">"မရနိုင်ပါ"</item> <item msgid="5044688398303285224">"ပိတ်"</item> diff --git a/packages/SystemUI/res/values-nb/strings.xml b/packages/SystemUI/res/values-nb/strings.xml index 149e1307cff2..07b979f9a223 100644 --- a/packages/SystemUI/res/values-nb/strings.xml +++ b/packages/SystemUI/res/values-nb/strings.xml @@ -127,24 +127,24 @@ <string name="screenrecord_save_error" msgid="5862648532560118815">"Feil ved lagring av skjermopptaket"</string> <string name="screenrecord_start_error" msgid="2200660692479682368">"Feil ved start av skjermopptaket"</string> <string name="screenrecord_stop_dialog_title" msgid="8716193661764511095">"Vil du stoppe opptaket?"</string> - <string name="screenrecord_stop_dialog_message" msgid="6262768207331626817">"Du tar opp hele skjermen"</string> - <string name="screenrecord_stop_dialog_message_specific_app" msgid="5995770227684523244">"Du tar opp <xliff:g id="APP_NAME">%1$s</xliff:g>"</string> + <string name="screenrecord_stop_dialog_message" msgid="6262768207331626817">"Du tar nå opp hele skjermen"</string> + <string name="screenrecord_stop_dialog_message_specific_app" msgid="5995770227684523244">"Du tar nå opp <xliff:g id="APP_NAME">%1$s</xliff:g>"</string> <string name="screenrecord_stop_dialog_button" msgid="2883812564938194350">"Stopp opptaket"</string> <string name="share_to_app_chip_accessibility_label" msgid="4210256229976947065">"Deler skjermen"</string> <string name="share_to_app_stop_dialog_title" msgid="9212915050910250438">"Vil du slutte å dele skjermen?"</string> - <string name="share_to_app_stop_dialog_message_entire_screen_with_host_app" msgid="522823522115375414">"Du deler hele skjermen med <xliff:g id="HOST_APP_NAME">%1$s</xliff:g>"</string> - <string name="share_to_app_stop_dialog_message_entire_screen" msgid="5090115386271179270">"Du deler hele skjermen med en app"</string> - <string name="share_to_app_stop_dialog_message_single_app_specific" msgid="5923772039347985172">"Du deler <xliff:g id="APP_BEING_SHARED_NAME">%1$s</xliff:g>"</string> - <string name="share_to_app_stop_dialog_message_single_app_generic" msgid="6681016774654578261">"Du deler en app"</string> + <string name="share_to_app_stop_dialog_message_entire_screen_with_host_app" msgid="522823522115375414">"Du deler nå hele skjermen med <xliff:g id="HOST_APP_NAME">%1$s</xliff:g>"</string> + <string name="share_to_app_stop_dialog_message_entire_screen" msgid="5090115386271179270">"Du deler nå hele skjermen med en app"</string> + <string name="share_to_app_stop_dialog_message_single_app_specific" msgid="5923772039347985172">"Du deler nå <xliff:g id="APP_BEING_SHARED_NAME">%1$s</xliff:g>"</string> + <string name="share_to_app_stop_dialog_message_single_app_generic" msgid="6681016774654578261">"Du deler nå en app"</string> <string name="share_to_app_stop_dialog_button" msgid="6334056916284230217">"Slutt å dele"</string> <string name="cast_screen_to_other_device_chip_accessibility_label" msgid="4687917476203009885">"Caster skjermen"</string> <string name="cast_to_other_device_stop_dialog_title" msgid="7836517190930357326">"Vil du stoppe castingen?"</string> - <string name="cast_to_other_device_stop_dialog_message_entire_screen_with_device" msgid="1474703115926205251">"Du caster hele skjermen til <xliff:g id="DEVICE_NAME">%1$s</xliff:g>"</string> - <string name="cast_to_other_device_stop_dialog_message_entire_screen" msgid="8419219169553867625">"Du caster hele skjermen til en enhet i nærheten"</string> - <string name="cast_to_other_device_stop_dialog_message_specific_app_with_device" msgid="2715934698604085519">"Du caster <xliff:g id="APP_BEING_SHARED_NAME">%1$s</xliff:g> til <xliff:g id="DEVICE_NAME">%2$s</xliff:g>"</string> - <string name="cast_to_other_device_stop_dialog_message_specific_app" msgid="8616103075630934513">"Du caster <xliff:g id="APP_BEING_SHARED_NAME">%1$s</xliff:g> til en enhet i nærheten"</string> - <string name="cast_to_other_device_stop_dialog_message_generic_with_device" msgid="9213582497852420203">"Du caster til <xliff:g id="DEVICE_NAME">%1$s</xliff:g>"</string> - <string name="cast_to_other_device_stop_dialog_message_generic" msgid="4100272100480415076">"Du caster skjermen til en enhet i nærheten"</string> + <string name="cast_to_other_device_stop_dialog_message_entire_screen_with_device" msgid="1474703115926205251">"Du caster nå hele skjermen til <xliff:g id="DEVICE_NAME">%1$s</xliff:g>"</string> + <string name="cast_to_other_device_stop_dialog_message_entire_screen" msgid="8419219169553867625">"Du caster nå hele skjermen til en enhet i nærheten"</string> + <string name="cast_to_other_device_stop_dialog_message_specific_app_with_device" msgid="2715934698604085519">"Du caster nå <xliff:g id="APP_BEING_SHARED_NAME">%1$s</xliff:g> til <xliff:g id="DEVICE_NAME">%2$s</xliff:g>"</string> + <string name="cast_to_other_device_stop_dialog_message_specific_app" msgid="8616103075630934513">"Du caster nå <xliff:g id="APP_BEING_SHARED_NAME">%1$s</xliff:g> til en enhet i nærheten"</string> + <string name="cast_to_other_device_stop_dialog_message_generic_with_device" msgid="9213582497852420203">"Du caster nå til <xliff:g id="DEVICE_NAME">%1$s</xliff:g>"</string> + <string name="cast_to_other_device_stop_dialog_message_generic" msgid="4100272100480415076">"Du caster nå skjermen til en enhet i nærheten"</string> <string name="cast_to_other_device_stop_dialog_button" msgid="6420183747435521834">"Stopp castingen"</string> <string name="close_dialog_button" msgid="4749497706540104133">"Lukk"</string> <string name="issuerecord_title" msgid="286627115110121849">"Funksjon for opptak av problemer"</string> @@ -388,6 +388,9 @@ <string name="performance" msgid="6552785217174378320">"Ytelse"</string> <string name="user_interface" msgid="3712869377953950887">"Brukergrensesnitt"</string> <string name="thermal" msgid="6758074791325414831">"Termisk"</string> + <string name="custom" msgid="3337456985275158299">"Egendefinert"</string> + <string name="custom_trace_settings_dialog_title" msgid="2608570500144830554">"Innstillinger for egendefinert spor"</string> + <string name="restore_default" msgid="5259420807486239755">"Gjenopprett standard"</string> <string name="quick_settings_onehanded_label" msgid="2416537930246274991">"Enhåndsmodus"</string> <string name="quick_settings_hearing_devices_label" msgid="7277170419679404129">"Høreapparater"</string> <string name="quick_settings_hearing_devices_connected" msgid="6519069502397037781">"Aktiv"</string> @@ -429,9 +432,13 @@ <string name="zen_modes_dialog_title" msgid="4159138230418567383">"Prioritetsmoduser"</string> <string name="zen_modes_dialog_done" msgid="6654130880256438950">"Ferdig"</string> <string name="zen_modes_dialog_settings" msgid="2310248023728936697">"Innstillinger"</string> - <!-- no translation found for zen_mode_on (9085304934016242591) --> + <string name="zen_mode_on" msgid="9085304934016242591">"På"</string> + <string name="zen_mode_off" msgid="1736604456618147306">"Av"</string> + <!-- no translation found for zen_mode_set_up (7457957033034460064) --> <skip /> - <!-- no translation found for zen_mode_off (1736604456618147306) --> + <!-- no translation found for zen_mode_no_manual_invocation (1769975741344633672) --> + <skip /> + <!-- no translation found for zen_mode_active_modes (1625850411578488856) --> <skip /> <string name="zen_priority_introduction" msgid="3159291973383796646">"Du blir ikke forstyrret av lyder og vibrasjoner, med unntak av alarmer, påminnelser, aktiviteter og oppringere du angir. Du kan fremdeles høre alt du velger å spille av, for eksempel musikk, videoer og spill."</string> <string name="zen_alarms_introduction" msgid="3987266042682300470">"Du blir ikke forstyrret av lyder og vibrasjoner, med unntak av alarmer. Du kan fremdeles høre alt du velger å spille av, for eksempel musikk, videoer og spill."</string> @@ -471,6 +478,8 @@ <string name="keyguard_indication_charging_time_slowly" msgid="301936949731705417">"<xliff:g id="PERCENTAGE">%2$s</xliff:g> • Lader sakte • Fulladet om <xliff:g id="CHARGING_TIME_LEFT">%1$s</xliff:g>"</string> <string name="keyguard_indication_charging_time_dock" msgid="3149328898931741271">"<xliff:g id="PERCENTAGE">%2$s</xliff:g> • Lader • Fulladet om <xliff:g id="CHARGING_TIME_LEFT">%1$s</xliff:g>"</string> <string name="accessibility_action_open_communal_hub" msgid="3081702792413787849">"Moduler på låseskjermen"</string> + <!-- no translation found for accessibility_announcement_communal_widget_added (6911593106099328271) --> + <skip /> <string name="communal_tutorial_indicator_text" msgid="4503010353591430123">"Sveip til venstre for å starte fellesveiledningen"</string> <string name="cta_tile_button_to_open_widget_editor" msgid="3871562362382963878">"Tilpass"</string> <string name="cta_tile_button_to_dismiss" msgid="3377597875997861754">"Lukk"</string> @@ -499,8 +508,7 @@ <string name="accessibility_action_label_place_widget" msgid="1914197458644168978">"plasser den valgte modulen"</string> <string name="communal_widget_picker_title" msgid="1953369090475731663">"Moduler på låseskjermen"</string> <string name="communal_widget_picker_description" msgid="490515450110487871">"Hvem som helst kan se moduler på låseskjermen – selv om nettbrettet er låst."</string> - <!-- no translation found for accessibility_action_label_unselect_widget (1041811747619468698) --> - <skip /> + <string name="accessibility_action_label_unselect_widget" msgid="1041811747619468698">"velg bort modul"</string> <string name="communal_widgets_disclaimer_title" msgid="1150954395585308868">"Låseskjermmoduler"</string> <string name="communal_widgets_disclaimer_text" msgid="1423545475160506349">"For å åpne en app ved hjelp av en modul må du bekrefte at det er deg. Husk også at hvem som helst kan se dem, selv om nettbrettet er låst. Noen moduler er kanskje ikke laget for å være på låseskjermen og kan være utrygge å legge til der."</string> <string name="communal_widgets_disclaimer_button" msgid="4423059765740780753">"Greit"</string> @@ -557,10 +565,8 @@ <string name="media_projection_action_text" msgid="3634906766918186440">"Start nå"</string> <string name="empty_shade_text" msgid="8935967157319717412">"Ingen varsler"</string> <string name="no_unseen_notif_text" msgid="395512586119868682">"Ingen nye varsler"</string> - <!-- no translation found for adaptive_notification_edu_hun_title (7790738150177329960) --> - <skip /> - <!-- no translation found for adaptive_notification_edu_hun_text (7743367744129536610) --> - <skip /> + <string name="adaptive_notification_edu_hun_title" msgid="7790738150177329960">"Varseldemping er slått på"</string> + <string name="adaptive_notification_edu_hun_text" msgid="7743367744129536610">"Enhetsvolumet og varsler reduseres automatisk i opptil 2 min når du får for mange varsler samtidig."</string> <string name="go_to_adaptive_notification_settings" msgid="2423690125178298479">"Slå av"</string> <string name="unlock_to_see_notif_text" msgid="7439033907167561227">"Lås opp for å se eldre varsler"</string> <string name="quick_settings_disclosure_parental_controls" msgid="2114102871438223600">"Denne enheten administreres av forelderen din"</string> @@ -1226,7 +1232,6 @@ <string name="accessibility_fingerprint_bouncer" msgid="7189102492498735519">"Autentisering kreves. Trykk på fingeravtrykkssensoren for å autentisere."</string> <string name="ongoing_phone_call_content_description" msgid="5332334388483099947">"Pågående telefonsamtale"</string> <string name="mobile_data_settings_title" msgid="3955246641380064901">"Mobildata"</string> - <string name="preference_summary_default_combination" msgid="8453246369903749670">"<xliff:g id="STATE">%1$s</xliff:g> / <xliff:g id="NETWORKMODE">%2$s</xliff:g>"</string> <string name="mobile_data_connection_active" msgid="944490013299018227">"Tilkoblet"</string> <string name="mobile_data_temp_connection_active" msgid="4590222725908806824">"Koblet til midlertidig"</string> <string name="mobile_data_poor_connection" msgid="819617772268371434">"Dårlig forbindelse"</string> @@ -1380,7 +1385,10 @@ <string name="touchpad_tutorial_done_button" msgid="176168488821755503">"Ferdig"</string> <string name="touchpad_tutorial_gesture_done" msgid="4784438360736821255">"Bra jobbet!"</string> <string name="touchpad_back_gesture_action_title" msgid="7199067250654332735">"Gå tilbake"</string> - <string name="touchpad_back_gesture_guidance" msgid="4222430588599527272">"For å gå tilbake, sveip til venstre eller høyre med tre fingre hvor som helst på styreflaten."</string> + <!-- no translation found for touchpad_back_gesture_guidance (6263750214998421587) --> + <skip /> + <!-- no translation found for touchpad_back_gesture_finished (5353616006999726249) --> + <skip /> <string name="touchpad_back_gesture_animation_content_description" msgid="2646107450922379918">"En styreflate med tre fingre som beveger seg til høyre og venstre"</string> <string name="touchpad_back_gesture_screen_animation_content_description" msgid="4036267494237748710">"Enhetsskjerm med animasjonen for tilbakebevegelse"</string> <string name="keyboard_backlight_dialog_title" msgid="8273102932345564724">"Bakgrunnslys for tastatur"</string> @@ -1388,28 +1396,16 @@ <string name="home_controls_dream_label" msgid="6567105701292324257">"Hjemkontroller"</string> <string name="home_controls_dream_description" msgid="4644150952104035789">"Gå raskt til hjemkontrollene som skjermsparer"</string> <string name="volume_undo_action" msgid="5815519725211877114">"Angre"</string> - <!-- no translation found for back_edu_toast_content (4530314597378982956) --> - <skip /> - <!-- no translation found for home_edu_toast_content (3381071147871955415) --> - <skip /> - <!-- no translation found for overview_edu_toast_content (5797030644017804518) --> - <skip /> - <!-- no translation found for all_apps_edu_toast_content (8807496014667211562) --> - <skip /> - <!-- no translation found for back_edu_notification_title (5624780717751357278) --> - <skip /> - <!-- no translation found for back_edu_notification_content (2497557451540954068) --> - <skip /> - <!-- no translation found for home_edu_notification_title (6097902076909654045) --> - <skip /> - <!-- no translation found for home_edu_notification_content (6631697734535766588) --> - <skip /> - <!-- no translation found for overview_edu_notification_title (1265824157319562406) --> - <skip /> - <!-- no translation found for overview_edu_notification_content (3578204677648432500) --> - <skip /> - <!-- no translation found for all_apps_edu_notification_title (372262997265569063) --> - <skip /> - <!-- no translation found for all_apps_edu_notification_content (3255070575694025585) --> - <skip /> + <string name="back_edu_toast_content" msgid="4530314597378982956">"For å gå tilbake, sveip til venstre eller høyre med tre fingre på styreflaten"</string> + <string name="home_edu_toast_content" msgid="3381071147871955415">"For å gå til startsiden, sveip opp med tre fingre på styreflaten"</string> + <string name="overview_edu_toast_content" msgid="5797030644017804518">"For å se nylige apper, sveip opp og hold med tre fingre på styreflaten"</string> + <string name="all_apps_edu_toast_content" msgid="8807496014667211562">"For å se alle appene dine, trykk på handlingstasten på tastaturet"</string> + <string name="back_edu_notification_title" msgid="5624780717751357278">"Bruk styreflaten for å gå tilbake"</string> + <string name="back_edu_notification_content" msgid="2497557451540954068">"Sveip til venstre eller høyre med tre fingre. Trykk for å lære flere bevegelser."</string> + <string name="home_edu_notification_title" msgid="6097902076909654045">"Bruk styreflaten for å gå til startsiden"</string> + <string name="home_edu_notification_content" msgid="6631697734535766588">"Sveip opp med tre fingre. Trykk for å lære flere bevegelser."</string> + <string name="overview_edu_notification_title" msgid="1265824157319562406">"Bruk styreflaten for å se nylige apper"</string> + <string name="overview_edu_notification_content" msgid="3578204677648432500">"Sveip opp og hold med tre fingre. Trykk for å lære flere bevegelser."</string> + <string name="all_apps_edu_notification_title" msgid="372262997265569063">"Bruk tastaturet for å se alle apper"</string> + <string name="all_apps_edu_notification_content" msgid="3255070575694025585">"Trykk på handlingstasten når som helst. Trykk for å lære flere bevegelser."</string> </resources> diff --git a/packages/SystemUI/res/values-nb/tiles_states_strings.xml b/packages/SystemUI/res/values-nb/tiles_states_strings.xml index e3d8eff19d7e..a9efd1d95a7d 100644 --- a/packages/SystemUI/res/values-nb/tiles_states_strings.xml +++ b/packages/SystemUI/res/values-nb/tiles_states_strings.xml @@ -56,11 +56,6 @@ <item msgid="5376619709702103243">"Av"</item> <item msgid="4875147066469902392">"På"</item> </string-array> - <string-array name="tile_states_modes"> - <item msgid="7764936419245199023">"Utilgjengelig"</item> - <item msgid="2004750556637773692">"Av"</item> - <item msgid="8968530753931637871">"På"</item> - </string-array> <string-array name="tile_states_flashlight"> <item msgid="3465257127433353857">"Utilgjengelig"</item> <item msgid="5044688398303285224">"Av"</item> diff --git a/packages/SystemUI/res/values-ne/strings.xml b/packages/SystemUI/res/values-ne/strings.xml index 01f7b404865b..67843fd719d8 100644 --- a/packages/SystemUI/res/values-ne/strings.xml +++ b/packages/SystemUI/res/values-ne/strings.xml @@ -388,6 +388,9 @@ <string name="performance" msgid="6552785217174378320">"पर्फर्मेन्स"</string> <string name="user_interface" msgid="3712869377953950887">"युजर इन्टरफेस"</string> <string name="thermal" msgid="6758074791325414831">"थर्मल"</string> + <string name="custom" msgid="3337456985275158299">"कस्टम"</string> + <string name="custom_trace_settings_dialog_title" msgid="2608570500144830554">"कस्टम ट्रेस सेटिङ"</string> + <string name="restore_default" msgid="5259420807486239755">"डिफल्ट सेटिङ रिस्टोर गर्नुहोस्"</string> <string name="quick_settings_onehanded_label" msgid="2416537930246274991">"एक हाते मोड"</string> <string name="quick_settings_hearing_devices_label" msgid="7277170419679404129">"हियरिङ डिभाइसहरू"</string> <string name="quick_settings_hearing_devices_connected" msgid="6519069502397037781">"सक्रिय छ"</string> @@ -431,6 +434,12 @@ <string name="zen_modes_dialog_settings" msgid="2310248023728936697">"सेटिङ"</string> <string name="zen_mode_on" msgid="9085304934016242591">"अन छ"</string> <string name="zen_mode_off" msgid="1736604456618147306">"अफ छ"</string> + <!-- no translation found for zen_mode_set_up (7457957033034460064) --> + <skip /> + <!-- no translation found for zen_mode_no_manual_invocation (1769975741344633672) --> + <skip /> + <!-- no translation found for zen_mode_active_modes (1625850411578488856) --> + <skip /> <string name="zen_priority_introduction" msgid="3159291973383796646">"तपाईंलाई अलार्म, रिमाइन्डर, कार्यक्रम र तपाईंले निर्दिष्ट गर्नुभएका कलरहरू बाहेकका ध्वनि र कम्पनहरूले बाधा पुऱ्याउने छैनन्। तपाईंले अझै सङ्गीत, भिडियो र खेलहरू लगायत आफूले प्ले गर्न छनौट गरेका जुनसुकै कुरा सुन्न सक्नुहुनेछ।"</string> <string name="zen_alarms_introduction" msgid="3987266042682300470">"तपाईंलाई अलार्महरू बाहेकका ध्वनि र कम्पनहरूले बाधा पुऱ्याउने छैनन्। तपाईंले अझै सङ्गीत, भिडियो र खेलहरू लगायत आफूले प्ले गर्न छनौट गरेका जुनसुकै कुरा सुन्न सक्नुहुनेछ।"</string> <string name="zen_priority_customize_button" msgid="4119213187257195047">" कस्टम बनाउनुहोस्"</string> @@ -469,6 +478,8 @@ <string name="keyguard_indication_charging_time_slowly" msgid="301936949731705417">"<xliff:g id="PERCENTAGE">%2$s</xliff:g> • बिस्तारै चार्ज हुँदै छ • <xliff:g id="CHARGING_TIME_LEFT">%1$s</xliff:g> मा पूरै चार्ज हुन्छ"</string> <string name="keyguard_indication_charging_time_dock" msgid="3149328898931741271">"<xliff:g id="PERCENTAGE">%2$s</xliff:g> • चार्ज हुँदै छ • <xliff:g id="CHARGING_TIME_LEFT">%1$s</xliff:g> मा फुल चार्ज हुने छ"</string> <string name="accessibility_action_open_communal_hub" msgid="3081702792413787849">"लक स्क्रिनमा भएका विजेटहरू"</string> + <!-- no translation found for accessibility_announcement_communal_widget_added (6911593106099328271) --> + <skip /> <string name="communal_tutorial_indicator_text" msgid="4503010353591430123">"कम्युनल ट्युटोरियल सुरु गर्न बायाँतिर स्वाइप गर्नुहोस्"</string> <string name="cta_tile_button_to_open_widget_editor" msgid="3871562362382963878">"कस्टमाइज गर्नुहोस्"</string> <string name="cta_tile_button_to_dismiss" msgid="3377597875997861754">"खारेज गर्नुहोस्"</string> @@ -554,10 +565,8 @@ <string name="media_projection_action_text" msgid="3634906766918186440">"अहिले न"</string> <string name="empty_shade_text" msgid="8935967157319717412">"कुनै सूचनाहरू छैनन्"</string> <string name="no_unseen_notif_text" msgid="395512586119868682">"कुनै पनि नयाँ सूचना छैन"</string> - <!-- no translation found for adaptive_notification_edu_hun_title (7790738150177329960) --> - <skip /> - <!-- no translation found for adaptive_notification_edu_hun_text (7743367744129536610) --> - <skip /> + <string name="adaptive_notification_edu_hun_title" msgid="7790738150177329960">"नोटिफिकेसन कुलडाउन अन छ"</string> + <string name="adaptive_notification_edu_hun_text" msgid="7743367744129536610">"तपाईंले एकै पटक धेरै नोटिफिकेसन प्राप्त गर्दा बढीमा २ मिनेटसम्म तपाईंको डिभाइसको भोल्युम र अलर्टहरूको सङ्ख्या स्वतः घटाइन्छ।"</string> <string name="go_to_adaptive_notification_settings" msgid="2423690125178298479">"अफ गर्नुहोस्"</string> <string name="unlock_to_see_notif_text" msgid="7439033907167561227">"पुराना सूचनाहरू हेर्न अनलक गर्नुहोस्"</string> <string name="quick_settings_disclosure_parental_controls" msgid="2114102871438223600">"यो डिभाइस तपाईंका अभिभावक व्यवस्थापन गर्नुहुन्छ"</string> @@ -1223,7 +1232,6 @@ <string name="accessibility_fingerprint_bouncer" msgid="7189102492498735519">"पुष्टि गर्नु पर्ने हुन्छ। पुष्टि गर्न फिंगरप्रिन्ट सेन्सर छुनुहोस्।"</string> <string name="ongoing_phone_call_content_description" msgid="5332334388483099947">"जारी फोन कल"</string> <string name="mobile_data_settings_title" msgid="3955246641380064901">"मोबाइल डेटा"</string> - <string name="preference_summary_default_combination" msgid="8453246369903749670">"<xliff:g id="STATE">%1$s</xliff:g> / <xliff:g id="NETWORKMODE">%2$s</xliff:g>"</string> <string name="mobile_data_connection_active" msgid="944490013299018227">"इन्टरनेटमा कनेक्ट गरिएको छ"</string> <string name="mobile_data_temp_connection_active" msgid="4590222725908806824">"यसमा केही समयका लागि कनेक्ट गरिएको हो"</string> <string name="mobile_data_poor_connection" msgid="819617772268371434">"इन्टरनेट राम्री चलेको छैन"</string> @@ -1377,7 +1385,10 @@ <string name="touchpad_tutorial_done_button" msgid="176168488821755503">"सम्पन्न भयो"</string> <string name="touchpad_tutorial_gesture_done" msgid="4784438360736821255">"अद्भुत!"</string> <string name="touchpad_back_gesture_action_title" msgid="7199067250654332735">"पछाडि जानुहोस्"</string> - <string name="touchpad_back_gesture_guidance" msgid="4222430588599527272">"पछाडि जान तिन वटा औँलाले टचप्याडमा कतै छोएर बायाँ वा दायाँतिर स्वाइप गर्नुहोस्।"</string> + <!-- no translation found for touchpad_back_gesture_guidance (6263750214998421587) --> + <skip /> + <!-- no translation found for touchpad_back_gesture_finished (5353616006999726249) --> + <skip /> <string name="touchpad_back_gesture_animation_content_description" msgid="2646107450922379918">"तिन वटा औँला दायाँ र बायाँ सारेको देखाइएको टचप्याड"</string> <string name="touchpad_back_gesture_screen_animation_content_description" msgid="4036267494237748710">"पछाडि जाने जेस्चरको एनिमेसन देखाइएको डिभाइसको स्क्रिन"</string> <string name="keyboard_backlight_dialog_title" msgid="8273102932345564724">"किबोर्ड ब्याकलाइट"</string> diff --git a/packages/SystemUI/res/values-ne/tiles_states_strings.xml b/packages/SystemUI/res/values-ne/tiles_states_strings.xml index e0c517a43394..c1b2f3420a40 100644 --- a/packages/SystemUI/res/values-ne/tiles_states_strings.xml +++ b/packages/SystemUI/res/values-ne/tiles_states_strings.xml @@ -56,11 +56,6 @@ <item msgid="5376619709702103243">"अफ छ"</item> <item msgid="4875147066469902392">"अन छ"</item> </string-array> - <string-array name="tile_states_modes"> - <item msgid="7764936419245199023">"उपलब्ध छैन"</item> - <item msgid="2004750556637773692">"अफ छ"</item> - <item msgid="8968530753931637871">"अन छ"</item> - </string-array> <string-array name="tile_states_flashlight"> <item msgid="3465257127433353857">"उपलब्ध छैन"</item> <item msgid="5044688398303285224">"अफ छ"</item> diff --git a/packages/SystemUI/res/values-nl/strings.xml b/packages/SystemUI/res/values-nl/strings.xml index 65fda39c7c46..d259a3d74154 100644 --- a/packages/SystemUI/res/values-nl/strings.xml +++ b/packages/SystemUI/res/values-nl/strings.xml @@ -388,6 +388,9 @@ <string name="performance" msgid="6552785217174378320">"Prestaties"</string> <string name="user_interface" msgid="3712869377953950887">"Gebruikersinterface"</string> <string name="thermal" msgid="6758074791325414831">"Thermisch"</string> + <string name="custom" msgid="3337456985275158299">"Aangepast"</string> + <string name="custom_trace_settings_dialog_title" msgid="2608570500144830554">"Aangepaste traceringsinstellingen"</string> + <string name="restore_default" msgid="5259420807486239755">"Standaardinstellingen terugzetten"</string> <string name="quick_settings_onehanded_label" msgid="2416537930246274991">"Bediening met 1 hand"</string> <string name="quick_settings_hearing_devices_label" msgid="7277170419679404129">"Hoortoestellen"</string> <string name="quick_settings_hearing_devices_connected" msgid="6519069502397037781">"Actief"</string> @@ -431,6 +434,12 @@ <string name="zen_modes_dialog_settings" msgid="2310248023728936697">"Instellingen"</string> <string name="zen_mode_on" msgid="9085304934016242591">"Aan"</string> <string name="zen_mode_off" msgid="1736604456618147306">"Uit"</string> + <!-- no translation found for zen_mode_set_up (7457957033034460064) --> + <skip /> + <!-- no translation found for zen_mode_no_manual_invocation (1769975741344633672) --> + <skip /> + <!-- no translation found for zen_mode_active_modes (1625850411578488856) --> + <skip /> <string name="zen_priority_introduction" msgid="3159291973383796646">"Je wordt niet gestoord door geluiden en trillingen, behalve bij wekkers, herinneringen, afspraken en specifieke bellers die je selecteert. Je kunt nog steeds alles horen wat je wilt afspelen, waaronder muziek, video\'s en games."</string> <string name="zen_alarms_introduction" msgid="3987266042682300470">"Je wordt niet gestoord door geluiden en trillingen, behalve bij wekkers. Je kunt nog steeds alles horen wat je wilt afspelen, waaronder muziek, video\'s en games."</string> <string name="zen_priority_customize_button" msgid="4119213187257195047">"Aanpassen"</string> @@ -469,6 +478,8 @@ <string name="keyguard_indication_charging_time_slowly" msgid="301936949731705417">"<xliff:g id="PERCENTAGE">%2$s</xliff:g> • Langzaam opladen • Vol over <xliff:g id="CHARGING_TIME_LEFT">%1$s</xliff:g>"</string> <string name="keyguard_indication_charging_time_dock" msgid="3149328898931741271">"<xliff:g id="PERCENTAGE">%2$s</xliff:g> • Opladen • Vol over <xliff:g id="CHARGING_TIME_LEFT">%1$s</xliff:g>"</string> <string name="accessibility_action_open_communal_hub" msgid="3081702792413787849">"Widgets op het vergrendelscherm"</string> + <!-- no translation found for accessibility_announcement_communal_widget_added (6911593106099328271) --> + <skip /> <string name="communal_tutorial_indicator_text" msgid="4503010353591430123">"Swipe naar links om de communitytutorial te starten"</string> <string name="cta_tile_button_to_open_widget_editor" msgid="3871562362382963878">"Aanpassen"</string> <string name="cta_tile_button_to_dismiss" msgid="3377597875997861754">"Sluiten"</string> @@ -554,10 +565,8 @@ <string name="media_projection_action_text" msgid="3634906766918186440">"Nu starten"</string> <string name="empty_shade_text" msgid="8935967157319717412">"Geen meldingen"</string> <string name="no_unseen_notif_text" msgid="395512586119868682">"Geen nieuwe meldingen"</string> - <!-- no translation found for adaptive_notification_edu_hun_title (7790738150177329960) --> - <skip /> - <!-- no translation found for adaptive_notification_edu_hun_text (7743367744129536610) --> - <skip /> + <string name="adaptive_notification_edu_hun_title" msgid="7790738150177329960">"Afkoelperiode van meldingen staat aan"</string> + <string name="adaptive_notification_edu_hun_text" msgid="7743367744129536610">"Je apparaatvolume en meldingen worden automatisch maximaal 2 minuten beperkt als je te veel meldingen tegelijk krijgt."</string> <string name="go_to_adaptive_notification_settings" msgid="2423690125178298479">"Uitzetten"</string> <string name="unlock_to_see_notif_text" msgid="7439033907167561227">"Ontgrendel om oudere meldingen te zien"</string> <string name="quick_settings_disclosure_parental_controls" msgid="2114102871438223600">"Dit apparaat wordt beheerd door je ouder"</string> @@ -1223,7 +1232,6 @@ <string name="accessibility_fingerprint_bouncer" msgid="7189102492498735519">"Verificatie vereist. Raak de vingerafdruksensor aan om de verificatie uit te voeren."</string> <string name="ongoing_phone_call_content_description" msgid="5332334388483099947">"Actief telefoongesprek"</string> <string name="mobile_data_settings_title" msgid="3955246641380064901">"Mobiele data"</string> - <string name="preference_summary_default_combination" msgid="8453246369903749670">"<xliff:g id="STATE">%1$s</xliff:g>/<xliff:g id="NETWORKMODE">%2$s</xliff:g>"</string> <string name="mobile_data_connection_active" msgid="944490013299018227">"Verbonden"</string> <string name="mobile_data_temp_connection_active" msgid="4590222725908806824">"Tijdelijk verbonden"</string> <string name="mobile_data_poor_connection" msgid="819617772268371434">"Matige verbinding"</string> @@ -1377,7 +1385,10 @@ <string name="touchpad_tutorial_done_button" msgid="176168488821755503">"Klaar"</string> <string name="touchpad_tutorial_gesture_done" msgid="4784438360736821255">"Goed werk!"</string> <string name="touchpad_back_gesture_action_title" msgid="7199067250654332735">"Terug"</string> - <string name="touchpad_back_gesture_guidance" msgid="4222430588599527272">"Als je wilt teruggaan, swipe je met 3 vingers naar links of rechts op de touchpad."</string> + <!-- no translation found for touchpad_back_gesture_guidance (6263750214998421587) --> + <skip /> + <!-- no translation found for touchpad_back_gesture_finished (5353616006999726249) --> + <skip /> <string name="touchpad_back_gesture_animation_content_description" msgid="2646107450922379918">"Touchpad met 3 vingers die naar rechts en links bewegen"</string> <string name="touchpad_back_gesture_screen_animation_content_description" msgid="4036267494237748710">"Apparaatscherm met animatie voor teruggebaar"</string> <string name="keyboard_backlight_dialog_title" msgid="8273102932345564724">"Achtergrondverlichting van toetsenbord"</string> diff --git a/packages/SystemUI/res/values-nl/tiles_states_strings.xml b/packages/SystemUI/res/values-nl/tiles_states_strings.xml index b23dc91fae83..c5d93610fb87 100644 --- a/packages/SystemUI/res/values-nl/tiles_states_strings.xml +++ b/packages/SystemUI/res/values-nl/tiles_states_strings.xml @@ -56,11 +56,6 @@ <item msgid="5376619709702103243">"Uit"</item> <item msgid="4875147066469902392">"Aan"</item> </string-array> - <string-array name="tile_states_modes"> - <item msgid="7764936419245199023">"Niet beschikbaar"</item> - <item msgid="2004750556637773692">"Uit"</item> - <item msgid="8968530753931637871">"Aan"</item> - </string-array> <string-array name="tile_states_flashlight"> <item msgid="3465257127433353857">"Niet beschikbaar"</item> <item msgid="5044688398303285224">"Uit"</item> diff --git a/packages/SystemUI/res/values-or/strings.xml b/packages/SystemUI/res/values-or/strings.xml index 5bc77eb04b5c..11681c939e7a 100644 --- a/packages/SystemUI/res/values-or/strings.xml +++ b/packages/SystemUI/res/values-or/strings.xml @@ -388,6 +388,9 @@ <string name="performance" msgid="6552785217174378320">"ପରଫରମାନ୍ସ"</string> <string name="user_interface" msgid="3712869377953950887">"ୟୁଜର ଇଣ୍ଟରଫେସ"</string> <string name="thermal" msgid="6758074791325414831">"ଥର୍ମାଲ"</string> + <string name="custom" msgid="3337456985275158299">"କଷ୍ଟମ"</string> + <string name="custom_trace_settings_dialog_title" msgid="2608570500144830554">"କଷ୍ଟମ ଟ୍ରେସ ସେଟିଂସ"</string> + <string name="restore_default" msgid="5259420807486239755">"ଡିଫଲ୍ଟ ରିଷ୍ଟୋର କରନ୍ତୁ"</string> <string name="quick_settings_onehanded_label" msgid="2416537930246274991">"ଏକ-ହାତ ମୋଡ"</string> <string name="quick_settings_hearing_devices_label" msgid="7277170419679404129">"ଶ୍ରବଣ ଡିଭାଇସଗୁଡ଼ିକ"</string> <string name="quick_settings_hearing_devices_connected" msgid="6519069502397037781">"ସକ୍ରିୟ"</string> @@ -429,9 +432,13 @@ <string name="zen_modes_dialog_title" msgid="4159138230418567383">"ପ୍ରାଥମିକତା ମୋଡ"</string> <string name="zen_modes_dialog_done" msgid="6654130880256438950">"ହୋଇଗଲା"</string> <string name="zen_modes_dialog_settings" msgid="2310248023728936697">"ସେଟିଂସ"</string> - <!-- no translation found for zen_mode_on (9085304934016242591) --> + <string name="zen_mode_on" msgid="9085304934016242591">"ଚାଲୁ ଅଛି"</string> + <string name="zen_mode_off" msgid="1736604456618147306">"ବନ୍ଦ ଅଛି"</string> + <!-- no translation found for zen_mode_set_up (7457957033034460064) --> <skip /> - <!-- no translation found for zen_mode_off (1736604456618147306) --> + <!-- no translation found for zen_mode_no_manual_invocation (1769975741344633672) --> + <skip /> + <!-- no translation found for zen_mode_active_modes (1625850411578488856) --> <skip /> <string name="zen_priority_introduction" msgid="3159291973383796646">"ଆଲାର୍ମ, ରିମାଇଣ୍ଡର୍, ଇଭେଣ୍ଟ ଏବଂ ଆପଣ ନିର୍ଦ୍ଦିଷ୍ଟ କରିଥିବା କଲର୍ଙ୍କ ବ୍ୟତୀତ ଆପଣଙ୍କ ଧ୍ୟାନ ଅନ୍ୟ କୌଣସି ଧ୍ୱନୀ ଏବଂ ଭାଇବ୍ରେଶନ୍ରେ ଆକର୍ଷଣ କରାଯିବନାହିଁ। ମ୍ୟୁଜିକ୍, ଭିଡିଓ ଏବଂ ଗେମ୍ ସମେତ ନିଜେ ଚଲାଇବାକୁ ବାଛିଥିବା ଅନ୍ୟ ସବୁକିଛି ଆପଣ ଶୁଣିପାରିବେ।"</string> <string name="zen_alarms_introduction" msgid="3987266042682300470">"ଆଲାର୍ମ ବ୍ୟତୀତ ଆପଣଙ୍କ ଧ୍ୟାନ ଅନ୍ୟ କୌଣସି ଧ୍ୱନୀ ଏବଂ ଭାଇବ୍ରେଶନ୍ରେ ଆକର୍ଷଣ କରାଯିବନାହିଁ। ମ୍ୟୁଜିକ୍, ଭିଡିଓ ଏବଂ ଗେମ୍ ସମେତ ନିଜେ ଚଲାଇବାକୁ ବାଛିଥିବା ଅନ୍ୟ ସବୁକିଛି ଆପଣ ଶୁଣିପାରିବେ।"</string> @@ -471,6 +478,8 @@ <string name="keyguard_indication_charging_time_slowly" msgid="301936949731705417">"<xliff:g id="PERCENTAGE">%2$s</xliff:g> • ଧୀରେ ଚାର୍ଜ ହେଉଛି • <xliff:g id="CHARGING_TIME_LEFT">%1$s</xliff:g>ରେ ସମ୍ପୂର୍ଣ୍ଣ ହେବ"</string> <string name="keyguard_indication_charging_time_dock" msgid="3149328898931741271">"<xliff:g id="PERCENTAGE">%2$s</xliff:g> • ଚାର୍ଜ ହେଉଛି • <xliff:g id="CHARGING_TIME_LEFT">%1$s</xliff:g>ରେ ସମ୍ପୂର୍ଣ୍ଣ ହେବ"</string> <string name="accessibility_action_open_communal_hub" msgid="3081702792413787849">"ଲକ ସ୍କ୍ରିନରେ ଥିବା ୱିଜେଟଗୁଡ଼ିକ"</string> + <!-- no translation found for accessibility_announcement_communal_widget_added (6911593106099328271) --> + <skip /> <string name="communal_tutorial_indicator_text" msgid="4503010353591430123">"କମ୍ୟୁନାଲ ଟ୍ୟୁଟୋରିଆଲ ଆରମ୍ଭ କରିବା ପାଇଁ ବାମକୁ ସ୍ୱାଇପ କରନ୍ତୁ"</string> <string name="cta_tile_button_to_open_widget_editor" msgid="3871562362382963878">"କଷ୍ଟମାଇଜ କରନ୍ତୁ"</string> <string name="cta_tile_button_to_dismiss" msgid="3377597875997861754">"ଖାରଜ କରନ୍ତୁ"</string> @@ -497,10 +506,9 @@ <string name="accessibility_action_label_select_widget" msgid="8897281501387398191">"ୱିଜେଟ ଚୟନ କରନ୍ତୁ"</string> <string name="accessibility_action_label_remove_widget" msgid="3373779447448758070">"ୱିଜେଟକୁ କାଢ଼ି ଦିଅନ୍ତୁ"</string> <string name="accessibility_action_label_place_widget" msgid="1914197458644168978">"ଚୟନିତ ୱିଜେଟ ରଖନ୍ତୁ"</string> - <string name="communal_widget_picker_title" msgid="1953369090475731663">"ଲକ ସ୍କ୍ରିନ ୱିଜେଟଗୁଡ଼ିକ"</string> + <string name="communal_widget_picker_title" msgid="1953369090475731663">"ଲକ ସ୍କ୍ରିନ ୱିଜେଟ"</string> <string name="communal_widget_picker_description" msgid="490515450110487871">"ଆପଣଙ୍କ ଟାବଲେଟ ଲକ ଥିଲେ ମଧ୍ୟ ଯେ କୌଣସି ବ୍ୟକ୍ତି ଲକ ସ୍କ୍ରିନରେ ୱିଜେଟକୁ ଭ୍ୟୁ କରିପାରିବେ।"</string> - <!-- no translation found for accessibility_action_label_unselect_widget (1041811747619468698) --> - <skip /> + <string name="accessibility_action_label_unselect_widget" msgid="1041811747619468698">"ୱିଜେଟକୁ ଅଚୟନ କରନ୍ତୁ"</string> <string name="communal_widgets_disclaimer_title" msgid="1150954395585308868">"ଲକ ସ୍କ୍ରିନ ୱିଜେଟ"</string> <string name="communal_widgets_disclaimer_text" msgid="1423545475160506349">"ଏକ ୱିଜେଟ ବ୍ୟବହାର କରି ଗୋଟିଏ ଆପ ଖୋଲିବା ପାଇଁ ଏହା ଆପଣ ଅଟନ୍ତି ବୋଲି ଆପଣଙ୍କୁ ଯାଞ୍ଚ କରିବାକୁ ହେବ। ଆହୁରି ମଧ୍ୟ, ଆପଣଙ୍କ ଟାବଲେଟ ଲକ ଥିଲେ ମଧ୍ୟ ଯେ କୌଣସି ବ୍ୟକ୍ତି ଏହାକୁ ଭ୍ୟୁ କରିପାରିବେ ବୋଲି ମନେ ରଖନ୍ତୁ। କିଛି ୱିଜେଟ ଆପଣଙ୍କ ଲକ ସ୍କ୍ରିନ ପାଇଁ ଉଦ୍ଦିଷ୍ଟ ହୋଇନଥାଇପାରେ ଏବଂ ଏଠାରେ ଯୋଗ କରିବା ଅସୁରକ୍ଷିତ ହୋଇପାରେ।"</string> <string name="communal_widgets_disclaimer_button" msgid="4423059765740780753">"ବୁଝିଗଲି"</string> @@ -557,10 +565,8 @@ <string name="media_projection_action_text" msgid="3634906766918186440">"ବର୍ତ୍ତମାନ ଆରମ୍ଭ କରନ୍ତୁ"</string> <string name="empty_shade_text" msgid="8935967157319717412">"କୌଣସି ବିଜ୍ଞପ୍ତି ନାହିଁ"</string> <string name="no_unseen_notif_text" msgid="395512586119868682">"କୌଣସି ନୂଆ ବିଜ୍ଞପ୍ତିଗୁଡ଼ିକ ନାହିଁ"</string> - <!-- no translation found for adaptive_notification_edu_hun_title (7790738150177329960) --> - <skip /> - <!-- no translation found for adaptive_notification_edu_hun_text (7743367744129536610) --> - <skip /> + <string name="adaptive_notification_edu_hun_title" msgid="7790738150177329960">"ବିଜ୍ଞପ୍ତି କୁଲଡାଉନ ଚାଲୁ ଅଛି"</string> + <string name="adaptive_notification_edu_hun_text" msgid="7743367744129536610">"ଆପଣ ଥରକେ ଏକାଧିକ ବିଜ୍ଞପ୍ତି ପ୍ରାପ୍ତ କଲେ ଆପଣଙ୍କ ଡିଭାଇସର ଭଲ୍ୟୁମ ଓ ଆଲର୍ଟ ସ୍ୱତଃ 2 ମିନିଟ ପର୍ଯ୍ୟନ୍ତ କମ ହୁଏ।"</string> <string name="go_to_adaptive_notification_settings" msgid="2423690125178298479">"ବନ୍ଦ କରନ୍ତୁ"</string> <string name="unlock_to_see_notif_text" msgid="7439033907167561227">"ପୁରୁଣା ବିଜ୍ଞପ୍ତିଗୁଡ଼ିକ ଦେଖିବାକୁ ଅନଲକ କରନ୍ତୁ"</string> <string name="quick_settings_disclosure_parental_controls" msgid="2114102871438223600">"ଏହି ଡିଭାଇସ୍ ଆପଣଙ୍କ ବାପାମାଙ୍କ ଦ୍ୱାରା ପରିଚାଳିତ"</string> @@ -1226,7 +1232,6 @@ <string name="accessibility_fingerprint_bouncer" msgid="7189102492498735519">"ପ୍ରମାଣୀକରଣ ଆବଶ୍ୟକ। ପ୍ରମାଣୀକରଣ କରିବାକୁ ଟିପଚିହ୍ନ ସେନ୍ସରକୁ ସ୍ପର୍ଶ କରନ୍ତୁ।"</string> <string name="ongoing_phone_call_content_description" msgid="5332334388483099947">"ଚାଲୁଥିବା ଫୋନ୍ କଲ୍"</string> <string name="mobile_data_settings_title" msgid="3955246641380064901">"ମୋବାଇଲ ଡାଟା"</string> - <string name="preference_summary_default_combination" msgid="8453246369903749670">"<xliff:g id="STATE">%1$s</xliff:g> / <xliff:g id="NETWORKMODE">%2$s</xliff:g>"</string> <string name="mobile_data_connection_active" msgid="944490013299018227">"ସଂଯୋଗ କରାଯାଇଛି"</string> <string name="mobile_data_temp_connection_active" msgid="4590222725908806824">"ଅସ୍ଥାୟୀ ରୂପେ କନେକ୍ଟ କରାଯାଇଛି"</string> <string name="mobile_data_poor_connection" msgid="819617772268371434">"ଦୁର୍ବଳ କନେକ୍ସନ"</string> @@ -1380,7 +1385,10 @@ <string name="touchpad_tutorial_done_button" msgid="176168488821755503">"ହୋଇଗଲା"</string> <string name="touchpad_tutorial_gesture_done" msgid="4784438360736821255">"ବଢ଼ିଆ କାମ!"</string> <string name="touchpad_back_gesture_action_title" msgid="7199067250654332735">"ପଛକୁ ଫେରନ୍ତୁ"</string> - <string name="touchpad_back_gesture_guidance" msgid="4222430588599527272">"ପଛକୁ ଫେରିବା ପାଇଁ ଯେ କୌଣସି ସ୍ଥାନରେ ତିନି ଆଙ୍ଗୁଠି ବ୍ୟବହାର କରି ବାମ କିମ୍ବା ଡାହାଣକୁ ସ୍ୱାଇପ କରନ୍ତୁ।"</string> + <!-- no translation found for touchpad_back_gesture_guidance (6263750214998421587) --> + <skip /> + <!-- no translation found for touchpad_back_gesture_finished (5353616006999726249) --> + <skip /> <string name="touchpad_back_gesture_animation_content_description" msgid="2646107450922379918">"ଡାହାଣ ଏବଂ ବାମକୁ ତିନି ଆଙ୍ଗୁଠି ମୁଭ କରୁଥିବା ଟଚପେଡ ଦେଖାଉଛି"</string> <string name="touchpad_back_gesture_screen_animation_content_description" msgid="4036267494237748710">"ଡିଭାଇସ ସ୍କ୍ରିନ ବେକ ଜେଶ୍ଚର ପାଇଁ ଆନିମେସନ ଦେଖାଉଛି"</string> <string name="keyboard_backlight_dialog_title" msgid="8273102932345564724">"କୀବୋର୍ଡ ବେକଲାଇଟ"</string> @@ -1388,28 +1396,16 @@ <string name="home_controls_dream_label" msgid="6567105701292324257">"ହୋମ କଣ୍ଟ୍ରୋଲ୍ସ"</string> <string name="home_controls_dream_description" msgid="4644150952104035789">"ସ୍କ୍ରିନସେଭର ଭାବେ ହୋମ କଣ୍ଟ୍ରୋଲ୍ସକୁ ଶୀଘ୍ର ଆକ୍ସେସ କରନ୍ତୁ"</string> <string name="volume_undo_action" msgid="5815519725211877114">"ଅନଡୁ କରନ୍ତୁ"</string> - <!-- no translation found for back_edu_toast_content (4530314597378982956) --> - <skip /> - <!-- no translation found for home_edu_toast_content (3381071147871955415) --> - <skip /> - <!-- no translation found for overview_edu_toast_content (5797030644017804518) --> - <skip /> - <!-- no translation found for all_apps_edu_toast_content (8807496014667211562) --> - <skip /> - <!-- no translation found for back_edu_notification_title (5624780717751357278) --> - <skip /> - <!-- no translation found for back_edu_notification_content (2497557451540954068) --> - <skip /> - <!-- no translation found for home_edu_notification_title (6097902076909654045) --> - <skip /> - <!-- no translation found for home_edu_notification_content (6631697734535766588) --> - <skip /> - <!-- no translation found for overview_edu_notification_title (1265824157319562406) --> - <skip /> - <!-- no translation found for overview_edu_notification_content (3578204677648432500) --> - <skip /> - <!-- no translation found for all_apps_edu_notification_title (372262997265569063) --> - <skip /> - <!-- no translation found for all_apps_edu_notification_content (3255070575694025585) --> - <skip /> + <string name="back_edu_toast_content" msgid="4530314597378982956">"ପଛକୁ ଫେରିବା ପାଇଁ ଟଚପେଡରେ ତିନୋଟି ଆଙ୍ଗୁଠିରେ ବାମ କିମ୍ବା ଡାହାଣ ସ୍ୱାଇପ କରନ୍ତୁ"</string> + <string name="home_edu_toast_content" msgid="3381071147871955415">"ହୋମକୁ ଯିବା ପାଇଁ ଟଚପେଡରେ ତିନୋଟି ଆଙ୍ଗୁଠିରେ ଉପରକୁ ସ୍ୱାଇପ କରନ୍ତୁ"</string> + <string name="overview_edu_toast_content" msgid="5797030644017804518">"ବର୍ତ୍ତମାନର ଆପ୍ସ ଭ୍ୟୁ କରିବାକୁ, ଟଚପେଡରେ ତିନୋଟି ଆଙ୍ଗୁଠିରେ ଉପରକୁ ସ୍ୱାଇପ କରି ଧରି ରଖନ୍ତୁ"</string> + <string name="all_apps_edu_toast_content" msgid="8807496014667211562">"ଆପଣଙ୍କ ସମସ୍ତ ଆପ୍ସ ଭ୍ୟୁ କରିବା ପାଇଁ ଆପଣଙ୍କ କୀବୋର୍ଡରେ ଆକ୍ସନ କୀ\'କୁ ଦବାନ୍ତୁ"</string> + <string name="back_edu_notification_title" msgid="5624780717751357278">"ପଛକୁ ଫେରିବା ପାଇଁ ଆପଣଙ୍କ ଟଚପେଡକୁ ବ୍ୟବହାର କରନ୍ତୁ"</string> + <string name="back_edu_notification_content" msgid="2497557451540954068">"ତିନୋଟି ଆଙ୍ଗୁଠିରେ ବାମ ବା ଡାହାଣକୁ ସ୍ୱାଇପ କରନ୍ତୁ। ଜେଶ୍ଚରଗୁଡ଼ିକ ବିଷୟରେ ଅଧିକ ଜାଣିବାକୁ ଟାପ କରନ୍ତୁ।"</string> + <string name="home_edu_notification_title" msgid="6097902076909654045">"ହୋମକୁ ଯିବା ପାଇଁ ଆପଣଙ୍କ ଟଚପେଡ ବ୍ୟବହାର କରନ୍ତୁ"</string> + <string name="home_edu_notification_content" msgid="6631697734535766588">"ତିନୋଟି ଆଙ୍ଗୁଠି ବ୍ୟବହାର କରି ଉପରକୁ ସ୍ୱାଇପ କରନ୍ତୁ। ଜେଶ୍ଚରଗୁଡ଼ିକ ବିଷୟରେ ଅଧିକ ଜାଣିବାକୁ ଟାପ କରନ୍ତୁ।"</string> + <string name="overview_edu_notification_title" msgid="1265824157319562406">"ବର୍ତ୍ତମାନର ଆପ୍ସ ଭ୍ୟୁ କରିବାକୁ ଆପଣଙ୍କ ଟଚପେଡକୁ ବ୍ୟବହାର କରନ୍ତୁ"</string> + <string name="overview_edu_notification_content" msgid="3578204677648432500">"ତିନୋଟି ଆଙ୍ଗୁଠିରେ ଉପରକୁ ସ୍ୱାଇପ କରି ଧରି ରଖନ୍ତୁ। ଜେଶ୍ଚରଗୁଡ଼ିକ ବିଷୟରେ ଅଧିକ ଜାଣିବାକୁ ଟାପ କରନ୍ତୁ।"</string> + <string name="all_apps_edu_notification_title" msgid="372262997265569063">"ସମସ୍ତ ଆପ୍ସ ଭ୍ୟୁ କରିବା ପାଇଁ ଆପଣଙ୍କ କୀବୋର୍ଡକୁ ବ୍ୟବହାର କରନ୍ତୁ"</string> + <string name="all_apps_edu_notification_content" msgid="3255070575694025585">"ଯେ କୌଣସି ସମୟରେ ଆକ୍ସନ କୀ\'କୁ ଦବାନ୍ତୁ। ଜେଶ୍ଚରଗୁଡ଼ିକ ବିଷୟରେ ଅଧିକ ଜାଣିବାକୁ ଟାପ କରନ୍ତୁ।"</string> </resources> diff --git a/packages/SystemUI/res/values-or/tiles_states_strings.xml b/packages/SystemUI/res/values-or/tiles_states_strings.xml index 3ab7e5d00d4a..fe187c2ff082 100644 --- a/packages/SystemUI/res/values-or/tiles_states_strings.xml +++ b/packages/SystemUI/res/values-or/tiles_states_strings.xml @@ -56,11 +56,6 @@ <item msgid="5376619709702103243">"ବନ୍ଦ ଅଛି"</item> <item msgid="4875147066469902392">"ଚାଲୁ ଅଛି"</item> </string-array> - <string-array name="tile_states_modes"> - <item msgid="7764936419245199023">"ଅନୁପଲବ୍ଧ"</item> - <item msgid="2004750556637773692">"ବନ୍ଦ ଅଛି"</item> - <item msgid="8968530753931637871">"ଚାଲୁ ଅଛି"</item> - </string-array> <string-array name="tile_states_flashlight"> <item msgid="3465257127433353857">"ଉପଲବ୍ଧ ନାହିଁ"</item> <item msgid="5044688398303285224">"ବନ୍ଦ ଅଛି"</item> diff --git a/packages/SystemUI/res/values-pa/strings.xml b/packages/SystemUI/res/values-pa/strings.xml index 9692789b2f7c..ef642ffb0dd6 100644 --- a/packages/SystemUI/res/values-pa/strings.xml +++ b/packages/SystemUI/res/values-pa/strings.xml @@ -388,6 +388,9 @@ <string name="performance" msgid="6552785217174378320">"ਕਾਰਗੁਜ਼ਾਰੀ"</string> <string name="user_interface" msgid="3712869377953950887">"ਯੂਜ਼ਰ ਇੰਟਰਫ਼ੇਸ"</string> <string name="thermal" msgid="6758074791325414831">"ਥਰਮਲ"</string> + <string name="custom" msgid="3337456985275158299">"ਵਿਉਂਤਬੱਧ"</string> + <string name="custom_trace_settings_dialog_title" msgid="2608570500144830554">"ਵਿਉਂਤਬੱਧ ਟ੍ਰੇਸ ਸੈਟਿੰਗਾਂ"</string> + <string name="restore_default" msgid="5259420807486239755">"ਪੂਰਵ ਨਿਰਧਾਰਿਤ ਨੂੰ ਮੁੜ-ਬਹਾਲ ਕਰੋ"</string> <string name="quick_settings_onehanded_label" msgid="2416537930246274991">"ਇੱਕ ਹੱਥ ਮੋਡ"</string> <string name="quick_settings_hearing_devices_label" msgid="7277170419679404129">"ਸੁਣਨ ਵਾਲੇ ਡੀਵਾਈਸ"</string> <string name="quick_settings_hearing_devices_connected" msgid="6519069502397037781">"ਕਿਰਿਆਸ਼ੀਲ"</string> @@ -429,9 +432,13 @@ <string name="zen_modes_dialog_title" msgid="4159138230418567383">"ਤਰਜੀਹ ਮੋਡ"</string> <string name="zen_modes_dialog_done" msgid="6654130880256438950">"ਹੋ ਗਿਆ"</string> <string name="zen_modes_dialog_settings" msgid="2310248023728936697">"ਸੈਟਿੰਗਾਂ"</string> - <!-- no translation found for zen_mode_on (9085304934016242591) --> + <string name="zen_mode_on" msgid="9085304934016242591">"ਚਾਲੂ"</string> + <string name="zen_mode_off" msgid="1736604456618147306">"ਬੰਦ"</string> + <!-- no translation found for zen_mode_set_up (7457957033034460064) --> <skip /> - <!-- no translation found for zen_mode_off (1736604456618147306) --> + <!-- no translation found for zen_mode_no_manual_invocation (1769975741344633672) --> + <skip /> + <!-- no translation found for zen_mode_active_modes (1625850411578488856) --> <skip /> <string name="zen_priority_introduction" msgid="3159291973383796646">"ਧੁਨੀਆਂ ਅਤੇ ਥਰਥਰਾਹਟਾਂ ਤੁਹਾਨੂੰ ਪਰੇਸ਼ਾਨ ਨਹੀਂ ਕਰਨਗੀਆਂ, ਸਿਵਾਏ ਅਲਾਰਮਾਂ, ਯਾਦ-ਦਹਾਨੀਆਂ, ਵਰਤਾਰਿਆਂ, ਅਤੇ ਤੁਹਾਡੇ ਵੱਲੋਂ ਨਿਰਧਾਰਤ ਕੀਤੇ ਕਾਲਰਾਂ ਦੀ ਸੂਰਤ ਵਿੱਚ। ਤੁਸੀਂ ਅਜੇ ਵੀ ਸੰਗੀਤ, ਵੀਡੀਓ ਅਤੇ ਗੇਮਾਂ ਸਮੇਤ ਆਪਣੀ ਚੋਣ ਅਨੁਸਾਰ ਕੁਝ ਵੀ ਸੁਣ ਸਕਦੇ ਹੋ।"</string> <string name="zen_alarms_introduction" msgid="3987266042682300470">"ਧੁਨੀਆਂ ਅਤੇ ਥਰਥਰਾਹਟਾਂ ਤੁਹਾਨੂੰ ਪਰੇਸ਼ਾਨ ਨਹੀਂ ਕਰਨਗੀਆਂ, ਸਿਵਾਏ ਅਲਾਰਮਾਂ ਦੀ ਸੂਰਤ ਵਿੱਚ। ਤੁਸੀਂ ਅਜੇ ਵੀ ਸੰਗੀਤ, ਵੀਡੀਓ ਅਤੇ ਗੇਮਾਂ ਸਮੇਤ ਆਪਣੀ ਚੋਣ ਅਨੁਸਾਰ ਕੁਝ ਵੀ ਸੁਣ ਸਕਦੇ ਹੋ।"</string> @@ -471,6 +478,8 @@ <string name="keyguard_indication_charging_time_slowly" msgid="301936949731705417">"<xliff:g id="PERCENTAGE">%2$s</xliff:g> • ਹੌਲੀ ਚਾਰਜ ਹੋ ਰਿਹਾ ਹੈ • <xliff:g id="CHARGING_TIME_LEFT">%1$s</xliff:g> ਵਿੱਚ ਪੂਰਾ ਚਾਰਜ ਹੋਵੇਗਾ"</string> <string name="keyguard_indication_charging_time_dock" msgid="3149328898931741271">"<xliff:g id="PERCENTAGE">%2$s</xliff:g> • ਚਾਰਜ ਹੋ ਰਿਹਾ ਹੈ • <xliff:g id="CHARGING_TIME_LEFT">%1$s</xliff:g> ਵਿੱਚ ਪੂਰਾ ਚਾਰਜ ਹੋਵੇਗਾ"</string> <string name="accessibility_action_open_communal_hub" msgid="3081702792413787849">"ਲਾਕ ਸਕ੍ਰੀਨ \'ਤੇ ਵਿਜੇਟ"</string> + <!-- no translation found for accessibility_announcement_communal_widget_added (6911593106099328271) --> + <skip /> <string name="communal_tutorial_indicator_text" msgid="4503010353591430123">"ਭਾਈਚਾਰਕ ਟਿਊਟੋਰੀਅਲ ਸ਼ੁਰੂ ਕਰਨ ਲਈ ਖੱਬੇ ਪਾਸੇ ਵੱਲ ਸਵਾਈਪ ਕਰੋ"</string> <string name="cta_tile_button_to_open_widget_editor" msgid="3871562362382963878">"ਵਿਉਂਤਬੱਧ ਕਰੋ"</string> <string name="cta_tile_button_to_dismiss" msgid="3377597875997861754">"ਖਾਰਜ ਕਰੋ"</string> @@ -499,8 +508,7 @@ <string name="accessibility_action_label_place_widget" msgid="1914197458644168978">"ਚੁਣੇ ਗਏ ਵਿਜੇਟ ਲਈ ਥਾਂ ਚੁਣੋ"</string> <string name="communal_widget_picker_title" msgid="1953369090475731663">"ਲਾਕ ਸਕ੍ਰੀਨ ਵਿਜੇਟ"</string> <string name="communal_widget_picker_description" msgid="490515450110487871">"ਕੋਈ ਵੀ ਤੁਹਾਡੀ ਲਾਕ ਸਕ੍ਰੀਨ \'ਤੇ ਵਿਜੇਟ ਦੇਖ ਸਕਦਾ ਹੈ, ਭਾਵੇਂ ਤੁਹਾਡਾ ਟੈਬਲੈੱਟ ਲਾਕ ਹੋਵੇ।"</string> - <!-- no translation found for accessibility_action_label_unselect_widget (1041811747619468698) --> - <skip /> + <string name="accessibility_action_label_unselect_widget" msgid="1041811747619468698">"ਵਿਜੇਟ ਨੂੰ ਅਣਚੁਣਿਆ ਕਰੋ"</string> <string name="communal_widgets_disclaimer_title" msgid="1150954395585308868">"ਲਾਕ ਸਕ੍ਰੀਨ ਵਿਜੇਟ"</string> <string name="communal_widgets_disclaimer_text" msgid="1423545475160506349">"ਵਿਜੇਟ ਦੀ ਵਰਤੋਂ ਕਰ ਕੇ ਐਪ ਖੋਲ੍ਹਣ ਲਈ, ਤੁਹਾਨੂੰ ਇਹ ਪੁਸ਼ਟੀ ਕਰਨ ਦੀ ਲੋੜ ਪਵੇਗੀ ਕਿ ਇਹ ਤੁਸੀਂ ਹੀ ਹੋ। ਨਾਲ ਹੀ, ਇਹ ਵੀ ਧਿਆਨ ਵਿੱਚ ਰੱਖੋ ਕਿ ਕੋਈ ਵੀ ਉਨ੍ਹਾਂ ਨੂੰ ਦੇਖ ਸਕਦਾ ਹੈ, ਭਾਵੇਂ ਤੁਹਾਡੀ ਟੈਬਲੈੱਟ ਲਾਕ ਹੋਵੇ। ਹੋ ਸਕਦਾ ਹੈ ਕਿ ਕੁਝ ਵਿਜੇਟ ਤੁਹਾਡੀ ਲਾਕ ਸਕ੍ਰੀਨ ਲਈ ਨਾ ਬਣੇ ਹੋਣ ਅਤੇ ਉਨ੍ਹਾਂ ਨੂੰ ਇੱਥੇ ਸ਼ਾਮਲ ਕਰਨਾ ਅਸੁਰੱਖਿਅਤ ਹੋਵੇ।"</string> <string name="communal_widgets_disclaimer_button" msgid="4423059765740780753">"ਸਮਝ ਲਿਆ"</string> @@ -557,10 +565,8 @@ <string name="media_projection_action_text" msgid="3634906766918186440">"ਹੁਣੇ ਸ਼ੁਰੂ ਕਰੋ"</string> <string name="empty_shade_text" msgid="8935967157319717412">"ਕੋਈ ਸੂਚਨਾ ਨਹੀਂ"</string> <string name="no_unseen_notif_text" msgid="395512586119868682">"ਕੋਈ ਨਵੀਂ ਸੂਚਨਾ ਨਹੀਂ ਹੈ"</string> - <!-- no translation found for adaptive_notification_edu_hun_title (7790738150177329960) --> - <skip /> - <!-- no translation found for adaptive_notification_edu_hun_text (7743367744129536610) --> - <skip /> + <string name="adaptive_notification_edu_hun_title" msgid="7790738150177329960">"ਨੋਟੀਫ਼ਿਕੇਸ਼ਨ ਕੂਲਡਾਊਨ ਚਾਲੂ ਹੈ"</string> + <string name="adaptive_notification_edu_hun_text" msgid="7743367744129536610">"ਇੱਕ ਵਾਰ \'ਚ ਕਈ ਸੂਚਨਾਵਾਂ ਮਿਲਣ \'ਤੇ, ਡੀਵਾਈਸ ਦੀ ਅਵਾਜ਼ ਤੇ ਅਲਰਟ ਵੱਧੋ-ਵੱਧ 2 ਮਿੰਟਾਂ ਲਈ ਆਪਣੇ ਆਪ ਘਟ ਹੋ ਜਾਂਦੇ ਹਨ।"</string> <string name="go_to_adaptive_notification_settings" msgid="2423690125178298479">"ਬੰਦ ਕਰੋ"</string> <string name="unlock_to_see_notif_text" msgid="7439033907167561227">"ਪੁਰਾਣੀਆਂ ਸੂਚਨਾਵਾਂ ਦੇਖਣ ਲਈ ਅਣਲਾਕ ਕਰੋ"</string> <string name="quick_settings_disclosure_parental_controls" msgid="2114102871438223600">"ਇਸ ਡੀਵਾਈਸ ਦਾ ਪ੍ਰਬੰਧਨ ਤੁਹਾਡੇ ਮਾਂ-ਪਿਓ ਵੱਲੋਂ ਕੀਤਾ ਜਾਂਦਾ ਹੈ"</string> @@ -1226,7 +1232,6 @@ <string name="accessibility_fingerprint_bouncer" msgid="7189102492498735519">"ਪ੍ਰਮਾਣੀਕਰਨ ਲੋੜੀਂਦਾ ਹੈ। ਪ੍ਰਮਾਣਿਤ ਕਰਨ ਲਈ ਫਿੰਗਰਪ੍ਰਿੰਟ ਸੈਂਸਰ ਨੂੰ ਸਪਰਸ਼ ਕਰੋ।"</string> <string name="ongoing_phone_call_content_description" msgid="5332334388483099947">"ਜਾਰੀ ਫ਼ੋਨ ਕਾਲ"</string> <string name="mobile_data_settings_title" msgid="3955246641380064901">"ਮੋਬਾਈਲ ਡਾਟਾ"</string> - <string name="preference_summary_default_combination" msgid="8453246369903749670">"<xliff:g id="STATE">%1$s</xliff:g> / <xliff:g id="NETWORKMODE">%2$s</xliff:g>"</string> <string name="mobile_data_connection_active" msgid="944490013299018227">"ਕਨੈਕਟ ਹੈ"</string> <string name="mobile_data_temp_connection_active" msgid="4590222725908806824">"ਕੁਝ ਸਮੇਂ ਲਈ ਕਨੈਕਟ ਹੈ"</string> <string name="mobile_data_poor_connection" msgid="819617772268371434">"ਖਰਾਬ ਕਨੈਕਸ਼ਨ"</string> @@ -1380,7 +1385,10 @@ <string name="touchpad_tutorial_done_button" msgid="176168488821755503">"ਹੋ ਗਿਆ"</string> <string name="touchpad_tutorial_gesture_done" msgid="4784438360736821255">"ਬਹੁਤ ਵਧੀਆ!"</string> <string name="touchpad_back_gesture_action_title" msgid="7199067250654332735">"ਵਾਪਸ ਜਾਓ"</string> - <string name="touchpad_back_gesture_guidance" msgid="4222430588599527272">"ਵਾਪਸ ਜਾਣ ਲਈ, ਟੱਚਪੈਡ \'ਤੇ ਕਿਤੇ ਵੀ ਤਿੰਨ ਉਂਗਲਾਂ ਦੀ ਵਰਤੋਂ ਕਰ ਕੇ ਖੱਬੇ ਜਾਂ ਸੱਜੇ ਪਾਸੇ ਵੱਲ ਸਵਾਈਪ ਕਰੋ।"</string> + <!-- no translation found for touchpad_back_gesture_guidance (6263750214998421587) --> + <skip /> + <!-- no translation found for touchpad_back_gesture_finished (5353616006999726249) --> + <skip /> <string name="touchpad_back_gesture_animation_content_description" msgid="2646107450922379918">"ਟੱਚਪੈਡ \'ਤੇ ਤਿੰਨ ਉਂਗਲਾਂ ਨੂੰ ਸੱਜੇ ਅਤੇ ਖੱਬੇ ਪਾਸੇ ਵੱਲ ਲਿਜਾਂਦੇ ਹੋਏ ਦਿਖਾਇਆ ਜਾ ਰਿਹਾ ਹੈ"</string> <string name="touchpad_back_gesture_screen_animation_content_description" msgid="4036267494237748710">"ਡੀਵਾਈਸ ਦੀ ਸਕ੍ਰੀਨ \'ਤੇ ਪਿੱਛੇ ਜਾਣ ਵਾਲੇ ਇਸ਼ਾਰੇ ਲਈ ਐਨੀਮੇਸ਼ਨ ਦਿਖਾਇਆ ਜਾ ਰਿਹਾ ਹੈ"</string> <string name="keyboard_backlight_dialog_title" msgid="8273102932345564724">"ਕੀ-ਬੋਰਡ ਬੈਕਲਾਈਟ"</string> @@ -1388,28 +1396,16 @@ <string name="home_controls_dream_label" msgid="6567105701292324257">"ਹੋਮ ਕੰਟਰੋਲ"</string> <string name="home_controls_dream_description" msgid="4644150952104035789">"ਸਕ੍ਰੀਨ-ਸੇਵਰ ਵਜੋਂ ਆਪਣੇ ਹੋਮ ਕੰਟਰੋਲਾਂ ਤੱਕ ਤੁਰੰਤ ਪਹੁੰਚ ਕਰੋ"</string> <string name="volume_undo_action" msgid="5815519725211877114">"ਅਣਕੀਤਾ ਕਰੋ"</string> - <!-- no translation found for back_edu_toast_content (4530314597378982956) --> - <skip /> - <!-- no translation found for home_edu_toast_content (3381071147871955415) --> - <skip /> - <!-- no translation found for overview_edu_toast_content (5797030644017804518) --> - <skip /> - <!-- no translation found for all_apps_edu_toast_content (8807496014667211562) --> - <skip /> - <!-- no translation found for back_edu_notification_title (5624780717751357278) --> - <skip /> - <!-- no translation found for back_edu_notification_content (2497557451540954068) --> - <skip /> - <!-- no translation found for home_edu_notification_title (6097902076909654045) --> - <skip /> - <!-- no translation found for home_edu_notification_content (6631697734535766588) --> - <skip /> - <!-- no translation found for overview_edu_notification_title (1265824157319562406) --> - <skip /> - <!-- no translation found for overview_edu_notification_content (3578204677648432500) --> - <skip /> - <!-- no translation found for all_apps_edu_notification_title (372262997265569063) --> - <skip /> - <!-- no translation found for all_apps_edu_notification_content (3255070575694025585) --> - <skip /> + <string name="back_edu_toast_content" msgid="4530314597378982956">"ਪਿੱਛੇ ਜਾਣ ਲਈ, ਟੱਚਪੈਡ \'ਤੇ ਤਿੰਨ ਉਂਗਲਾਂ ਨਾਲ ਖੱਬੇ ਜਾਂ ਸੱਜੇ ਪਾਸੇ ਵੱਲ ਸਵਾਈਪ ਕਰੋ"</string> + <string name="home_edu_toast_content" msgid="3381071147871955415">"ਹੋਮ \'ਤੇ ਜਾਣ ਲਈ, ਟੱਚਪੈਡ \'ਤੇ ਤਿੰਨ ਉਂਗਲਾਂ ਨਾਲ ਉੱਪਰ ਵੱਲ ਸਵਾਈਪ ਕਰੋ"</string> + <string name="overview_edu_toast_content" msgid="5797030644017804518">"ਹਾਲੀਆ ਐਪਾਂ ਨੂੰ ਦੇਖਣ ਲਈ, ਟੱਚਪੈਡ \'ਤੇ ਤਿੰਨ ਉਂਗਲਾਂ ਨਾਲ ਉੱਪਰ ਵੱਲ ਸਵਾਈਪ ਕਰ ਕੇ ਦਬਾਈ ਰੱਖੋ"</string> + <string name="all_apps_edu_toast_content" msgid="8807496014667211562">"ਆਪਣੀਆਂ ਸਾਰੀਆਂ ਐਪਾਂ ਨੂੰ ਦੇਖਣ ਲਈ, ਆਪਣੇ ਕੀ-ਬੋਰਡ \'ਤੇ ਕਾਰਵਾਈ ਕੁੰਜੀ ਨੂੰ ਦਬਾਓ"</string> + <string name="back_edu_notification_title" msgid="5624780717751357278">"ਪਿੱਛੇ ਜਾਣ ਲਈ ਆਪਣੇ ਟੱਚਪੈਡ ਦੀ ਵਰਤੋਂ ਕਰੋ"</string> + <string name="back_edu_notification_content" msgid="2497557451540954068">"ਤਿੰਨ ਉਂਗਲਾਂ ਦੀ ਵਰਤੋਂ ਕਰ ਕੇ ਖੱਬੇ ਜਾਂ ਸੱਜੇ ਪਾਸੇ ਵੱਲ ਸਵਾਈਪ ਕਰੋ। ਹੋਰ ਇਸ਼ਾਰਿਆਂ ਨੂੰ ਜਾਣਨ ਲਈ ਟੈਪ ਕਰੋ।"</string> + <string name="home_edu_notification_title" msgid="6097902076909654045">"ਹੋਮ \'ਤੇ ਜਾਣ ਲਈ ਆਪਣੇ ਟੱਚਪੈਡ ਦੀ ਵਰਤੋਂ ਕਰੋ"</string> + <string name="home_edu_notification_content" msgid="6631697734535766588">"ਤਿੰਨ ਉਂਗਲਾਂ ਦੀ ਵਰਤੋਂ ਕਰ ਕੇ ਉੱਪਰ ਵੱਲ ਸਵਾਈਪ ਕਰੋ। ਹੋਰ ਇਸ਼ਾਰਿਆਂ ਨੂੰ ਜਾਣਨ ਲਈ ਟੈਪ ਕਰੋ।"</string> + <string name="overview_edu_notification_title" msgid="1265824157319562406">"ਹਾਲੀਆ ਐਪਾਂ ਦੇਖਣ ਲਈ ਆਪਣੇ ਟੱਚਪੈਡ ਦੀ ਵਰਤੋਂ ਕਰੋ"</string> + <string name="overview_edu_notification_content" msgid="3578204677648432500">"ਤਿੰਨ ਉਂਗਲਾਂ ਦੀ ਵਰਤੋਂ ਕਰ ਕੇ ਉੱਪਰ ਵੱਲ ਸਵਾਈਪ ਕਰ ਕੇ ਦਬਾਈ ਰੱਖੋ। ਹੋਰ ਇਸ਼ਾਰਿਆਂ ਨੂੰ ਜਾਣਨ ਲਈ ਟੈਪ ਕਰੋ।"</string> + <string name="all_apps_edu_notification_title" msgid="372262997265569063">"ਸਾਰੀਆਂ ਐਪਾਂ ਨੂੰ ਦੇਖਣ ਲਈ ਆਪਣਾ ਕੀ-ਬੋਰਡ ਵਰਤੋ"</string> + <string name="all_apps_edu_notification_content" msgid="3255070575694025585">"ਕਿਸੇ ਵੀ ਸਮੇਂ ਕਾਰਵਾਈ ਕੁੰਜੀ ਦਬਾਓ। ਹੋਰ ਇਸ਼ਾਰਿਆਂ ਨੂੰ ਜਾਣਨ ਲਈ ਟੈਪ ਕਰੋ।"</string> </resources> diff --git a/packages/SystemUI/res/values-pa/tiles_states_strings.xml b/packages/SystemUI/res/values-pa/tiles_states_strings.xml index c91062dad185..62dc05ad67bb 100644 --- a/packages/SystemUI/res/values-pa/tiles_states_strings.xml +++ b/packages/SystemUI/res/values-pa/tiles_states_strings.xml @@ -56,11 +56,6 @@ <item msgid="5376619709702103243">"ਬੰਦ ਹੈ"</item> <item msgid="4875147066469902392">"ਚਾਲੂ ਹੈ"</item> </string-array> - <string-array name="tile_states_modes"> - <item msgid="7764936419245199023">"ਉਪਲਬਧ ਨਹੀਂ"</item> - <item msgid="2004750556637773692">"ਬੰਦ"</item> - <item msgid="8968530753931637871">"ਚਾਲੂ"</item> - </string-array> <string-array name="tile_states_flashlight"> <item msgid="3465257127433353857">"ਅਣਉਪਲਬਧ ਹੈ"</item> <item msgid="5044688398303285224">"ਬੰਦ ਹੈ"</item> diff --git a/packages/SystemUI/res/values-pl/strings.xml b/packages/SystemUI/res/values-pl/strings.xml index 3a01cc9bb11c..d0e1e11e5727 100644 --- a/packages/SystemUI/res/values-pl/strings.xml +++ b/packages/SystemUI/res/values-pl/strings.xml @@ -388,6 +388,9 @@ <string name="performance" msgid="6552785217174378320">"Wydajność"</string> <string name="user_interface" msgid="3712869377953950887">"Interfejs"</string> <string name="thermal" msgid="6758074791325414831">"Termografia"</string> + <string name="custom" msgid="3337456985275158299">"Niestandardowe"</string> + <string name="custom_trace_settings_dialog_title" msgid="2608570500144830554">"Niestandardowe ustawienia śladu"</string> + <string name="restore_default" msgid="5259420807486239755">"Przywróć wartości domyślne"</string> <string name="quick_settings_onehanded_label" msgid="2416537930246274991">"Tryb jednej ręki"</string> <string name="quick_settings_hearing_devices_label" msgid="7277170419679404129">"Urządzenia słuchowe"</string> <string name="quick_settings_hearing_devices_connected" msgid="6519069502397037781">"Aktywne"</string> @@ -429,9 +432,13 @@ <string name="zen_modes_dialog_title" msgid="4159138230418567383">"Tryby priorytetowe"</string> <string name="zen_modes_dialog_done" msgid="6654130880256438950">"Gotowe"</string> <string name="zen_modes_dialog_settings" msgid="2310248023728936697">"Ustawienia"</string> - <!-- no translation found for zen_mode_on (9085304934016242591) --> + <string name="zen_mode_on" msgid="9085304934016242591">"Wł."</string> + <string name="zen_mode_off" msgid="1736604456618147306">"Wył."</string> + <!-- no translation found for zen_mode_set_up (7457957033034460064) --> <skip /> - <!-- no translation found for zen_mode_off (1736604456618147306) --> + <!-- no translation found for zen_mode_no_manual_invocation (1769975741344633672) --> + <skip /> + <!-- no translation found for zen_mode_active_modes (1625850411578488856) --> <skip /> <string name="zen_priority_introduction" msgid="3159291973383796646">"Nie będą Cię niepokoić żadne dźwięki ani wibracje z wyjątkiem alarmów, przypomnień, wydarzeń i połączeń od wybranych osób. Będziesz słyszeć wszystkie odtwarzane treści, takie jak muzyka, filmy czy gry."</string> <string name="zen_alarms_introduction" msgid="3987266042682300470">"Nie będą Cię niepokoić żadne dźwięki ani wibracje z wyjątkiem alarmów. Będziesz słyszeć wszystkie odtwarzane treści, takie jak muzyka, filmy czy gry."</string> @@ -471,6 +478,8 @@ <string name="keyguard_indication_charging_time_slowly" msgid="301936949731705417">"<xliff:g id="PERCENTAGE">%2$s</xliff:g> • Wolne ładowanie • Pełne naładowanie za <xliff:g id="CHARGING_TIME_LEFT">%1$s</xliff:g>"</string> <string name="keyguard_indication_charging_time_dock" msgid="3149328898931741271">"<xliff:g id="PERCENTAGE">%2$s</xliff:g> • Ładowanie • Pełne naładowanie za <xliff:g id="CHARGING_TIME_LEFT">%1$s</xliff:g>"</string> <string name="accessibility_action_open_communal_hub" msgid="3081702792413787849">"Widżety na ekranie blokady"</string> + <!-- no translation found for accessibility_announcement_communal_widget_added (6911593106099328271) --> + <skip /> <string name="communal_tutorial_indicator_text" msgid="4503010353591430123">"Aby uruchomić wspólny samouczek, przeciągnij palcem w lewo"</string> <string name="cta_tile_button_to_open_widget_editor" msgid="3871562362382963878">"Dostosuj"</string> <string name="cta_tile_button_to_dismiss" msgid="3377597875997861754">"Zamknij"</string> @@ -499,8 +508,7 @@ <string name="accessibility_action_label_place_widget" msgid="1914197458644168978">"umieść wybrany widżet"</string> <string name="communal_widget_picker_title" msgid="1953369090475731663">"Widżety na ekranie blokady"</string> <string name="communal_widget_picker_description" msgid="490515450110487871">"Każdy zobaczy widżety na ekranie blokady, nawet gdy tablet jest zablokowany."</string> - <!-- no translation found for accessibility_action_label_unselect_widget (1041811747619468698) --> - <skip /> + <string name="accessibility_action_label_unselect_widget" msgid="1041811747619468698">"odznacz widżet"</string> <string name="communal_widgets_disclaimer_title" msgid="1150954395585308868">"Widżety na ekranie blokady"</string> <string name="communal_widgets_disclaimer_text" msgid="1423545475160506349">"Aby otworzyć aplikację za pomocą widżetu, musisz potwierdzić swoją tożsamość. Pamiętaj też, że każdy będzie mógł wyświetlić widżety nawet wtedy, gdy tablet będzie zablokowany. Niektóre widżety mogą nie być przeznaczone do umieszczenia na ekranie blokady i ich dodanie w tym miejscu może być niebezpieczne."</string> <string name="communal_widgets_disclaimer_button" msgid="4423059765740780753">"OK"</string> @@ -557,10 +565,8 @@ <string name="media_projection_action_text" msgid="3634906766918186440">"Rozpocznij teraz"</string> <string name="empty_shade_text" msgid="8935967157319717412">"Brak powiadomień"</string> <string name="no_unseen_notif_text" msgid="395512586119868682">"Brak nowych powiadomień"</string> - <!-- no translation found for adaptive_notification_edu_hun_title (7790738150177329960) --> - <skip /> - <!-- no translation found for adaptive_notification_edu_hun_text (7743367744129536610) --> - <skip /> + <string name="adaptive_notification_edu_hun_title" msgid="7790738150177329960">"Wyciszanie powiadomień jest włączone"</string> + <string name="adaptive_notification_edu_hun_text" msgid="7743367744129536610">"Gdy otrzymasz za dużo powiadomień, dźwięk i alerty zostaną automatycznie wyciszone na maks. 2 min."</string> <string name="go_to_adaptive_notification_settings" msgid="2423690125178298479">"Wyłącz"</string> <string name="unlock_to_see_notif_text" msgid="7439033907167561227">"Odblokuj i zobacz starsze powiadomienia"</string> <string name="quick_settings_disclosure_parental_controls" msgid="2114102871438223600">"Tym urządzeniem zarządza Twój rodzic"</string> @@ -1226,7 +1232,6 @@ <string name="accessibility_fingerprint_bouncer" msgid="7189102492498735519">"Wymagane uwierzytelnienie. Dotknij czytnika liniii papilarnych, by uwierzytelnić."</string> <string name="ongoing_phone_call_content_description" msgid="5332334388483099947">"Aktywne połączenie"</string> <string name="mobile_data_settings_title" msgid="3955246641380064901">"Mobilna transmisja danych"</string> - <string name="preference_summary_default_combination" msgid="8453246369903749670">"<xliff:g id="STATE">%1$s</xliff:g>/<xliff:g id="NETWORKMODE">%2$s</xliff:g>"</string> <string name="mobile_data_connection_active" msgid="944490013299018227">"Połączono"</string> <string name="mobile_data_temp_connection_active" msgid="4590222725908806824">"Tymczasowe połączenie"</string> <string name="mobile_data_poor_connection" msgid="819617772268371434">"Słabe połączenie"</string> @@ -1380,7 +1385,10 @@ <string name="touchpad_tutorial_done_button" msgid="176168488821755503">"Gotowe"</string> <string name="touchpad_tutorial_gesture_done" msgid="4784438360736821255">"Świetnie!"</string> <string name="touchpad_back_gesture_action_title" msgid="7199067250654332735">"Wróć"</string> - <string name="touchpad_back_gesture_guidance" msgid="4222430588599527272">"Aby wrócić, przesuń 3 palcami w lewo lub w prawo w dowolnym miejscu touchpada."</string> + <!-- no translation found for touchpad_back_gesture_guidance (6263750214998421587) --> + <skip /> + <!-- no translation found for touchpad_back_gesture_finished (5353616006999726249) --> + <skip /> <string name="touchpad_back_gesture_animation_content_description" msgid="2646107450922379918">"3 palce na touchpadzie poruszające się w prawo i w lewo"</string> <string name="touchpad_back_gesture_screen_animation_content_description" msgid="4036267494237748710">"Ekran urządzenia z animacją gestu cofania"</string> <string name="keyboard_backlight_dialog_title" msgid="8273102932345564724">"Podświetlenie klawiatury"</string> @@ -1388,28 +1396,16 @@ <string name="home_controls_dream_label" msgid="6567105701292324257">"Sterowanie domem"</string> <string name="home_controls_dream_description" msgid="4644150952104035789">"Szybki dostęp do sterowania domem na wygaszaczu ekranu"</string> <string name="volume_undo_action" msgid="5815519725211877114">"Cofnij"</string> - <!-- no translation found for back_edu_toast_content (4530314597378982956) --> - <skip /> - <!-- no translation found for home_edu_toast_content (3381071147871955415) --> - <skip /> - <!-- no translation found for overview_edu_toast_content (5797030644017804518) --> - <skip /> - <!-- no translation found for all_apps_edu_toast_content (8807496014667211562) --> - <skip /> - <!-- no translation found for back_edu_notification_title (5624780717751357278) --> - <skip /> - <!-- no translation found for back_edu_notification_content (2497557451540954068) --> - <skip /> - <!-- no translation found for home_edu_notification_title (6097902076909654045) --> - <skip /> - <!-- no translation found for home_edu_notification_content (6631697734535766588) --> - <skip /> - <!-- no translation found for overview_edu_notification_title (1265824157319562406) --> - <skip /> - <!-- no translation found for overview_edu_notification_content (3578204677648432500) --> - <skip /> - <!-- no translation found for all_apps_edu_notification_title (372262997265569063) --> - <skip /> - <!-- no translation found for all_apps_edu_notification_content (3255070575694025585) --> - <skip /> + <string name="back_edu_toast_content" msgid="4530314597378982956">"Aby przejść wstecz, przesuń w prawo lub lewo za pomocą 3 palców na touchpadzie."</string> + <string name="home_edu_toast_content" msgid="3381071147871955415">"Aby przejść do ekranu głównego, przesuń w górę za pomocą 3 palców na touchpadzie"</string> + <string name="overview_edu_toast_content" msgid="5797030644017804518">"Aby wyświetlić ostatnie aplikacje, przesuń w górę za pomocą 3 palców na touchpadzie i przytrzymaj."</string> + <string name="all_apps_edu_toast_content" msgid="8807496014667211562">"Aby wyświetlić wszystkie swoje aplikacje, naciśnij klawisz działania na klawiaturze"</string> + <string name="back_edu_notification_title" msgid="5624780717751357278">"Przechodzenie wstecz za pomocą touchpada"</string> + <string name="back_edu_notification_content" msgid="2497557451540954068">"Przesuń w prawo lub lewo za pomocą 3 palców. Kliknij, aby poznać więcej gestów."</string> + <string name="home_edu_notification_title" msgid="6097902076909654045">"Przechodzenie do ekranu głównego za pomocą touchpada"</string> + <string name="home_edu_notification_content" msgid="6631697734535766588">"Przesuń w górę za pomocą 3 palców. Kliknij, aby poznać więcej gestów."</string> + <string name="overview_edu_notification_title" msgid="1265824157319562406">"Wyświetlanie ostatnio używanych aplikacji za pomocą touchpada"</string> + <string name="overview_edu_notification_content" msgid="3578204677648432500">"Przesuń w górę za pomocą 3 palców i przytrzymaj. Kliknij, aby poznać więcej gestów."</string> + <string name="all_apps_edu_notification_title" msgid="372262997265569063">"Wyświetlanie wszystkich aplikacji za pomocą klawiatury"</string> + <string name="all_apps_edu_notification_content" msgid="3255070575694025585">"Naciśnij klawisz działania w dowolnym momencie. Kliknij, aby poznać więcej gestów."</string> </resources> diff --git a/packages/SystemUI/res/values-pl/tiles_states_strings.xml b/packages/SystemUI/res/values-pl/tiles_states_strings.xml index 2190cf81a3fa..5aa719f2ea75 100644 --- a/packages/SystemUI/res/values-pl/tiles_states_strings.xml +++ b/packages/SystemUI/res/values-pl/tiles_states_strings.xml @@ -56,11 +56,6 @@ <item msgid="5376619709702103243">"Wyłączone"</item> <item msgid="4875147066469902392">"Włączone"</item> </string-array> - <string-array name="tile_states_modes"> - <item msgid="7764936419245199023">"Niedostępne"</item> - <item msgid="2004750556637773692">"Wyłączono"</item> - <item msgid="8968530753931637871">"Włączono"</item> - </string-array> <string-array name="tile_states_flashlight"> <item msgid="3465257127433353857">"Niedostępny"</item> <item msgid="5044688398303285224">"Wyłączona"</item> diff --git a/packages/SystemUI/res/values-pt-rBR/strings.xml b/packages/SystemUI/res/values-pt-rBR/strings.xml index 6a2bc58e2741..e74f57899b3f 100644 --- a/packages/SystemUI/res/values-pt-rBR/strings.xml +++ b/packages/SystemUI/res/values-pt-rBR/strings.xml @@ -218,7 +218,7 @@ <string name="biometric_re_enroll_notification_content" msgid="8685925877186288180">"Ação necessária para melhorar a segurança e o desempenho"</string> <string name="fingerprint_re_enroll_notification_title" msgid="4539432429683916604">"Configurar o Desbloqueio por impressão digital de novo"</string> <string name="fingerprint_re_enroll_notification_name" msgid="630798657797645704">"Desbloqueio por impressão digital"</string> - <string name="fingerprint_re_enroll_dialog_title" msgid="3526033128113925780">"Configurar o Desbloqueio por impressão digital"</string> + <string name="fingerprint_re_enroll_dialog_title" msgid="3526033128113925780">"Configurar o Desbloqueio por impressão digital"</string> <string name="fingerprint_re_enroll_dialog_content" msgid="4866561176695984879">"Os modelos e as imagens atuais serão excluídos para reconfigurar o Desbloqueio por impressão digital.\n\nDepois disso, você vai precisar configurar esse recurso de novo para desbloquear o smartphone com o dedo ou confirmar sua identidade."</string> <string name="fingerprint_re_enroll_dialog_content_singular" msgid="3083663339787381218">"O modelo e as imagens atuais serão excluídos para reconfigurar o Desbloqueio por impressão digital.\n\nDepois disso, você vai precisar configurar esse recurso de novo para desbloquear o smartphone com o dedo ou confirmar sua identidade."</string> <string name="fingerprint_reenroll_failure_dialog_content" msgid="4733768492747300666">"Não foi possível configurar o Desbloqueio por impressão digital. Acesse as Configurações e tente de novo."</string> @@ -388,6 +388,9 @@ <string name="performance" msgid="6552785217174378320">"Desempenho"</string> <string name="user_interface" msgid="3712869377953950887">"Interface do usuário"</string> <string name="thermal" msgid="6758074791325414831">"Térmico"</string> + <string name="custom" msgid="3337456985275158299">"Personalizado"</string> + <string name="custom_trace_settings_dialog_title" msgid="2608570500144830554">"Configurações de rastreamento personalizado"</string> + <string name="restore_default" msgid="5259420807486239755">"Restaurar padrão"</string> <string name="quick_settings_onehanded_label" msgid="2416537930246274991">"Modo uma mão"</string> <string name="quick_settings_hearing_devices_label" msgid="7277170419679404129">"Aparelhos auditivos"</string> <string name="quick_settings_hearing_devices_connected" msgid="6519069502397037781">"Ativos"</string> @@ -429,9 +432,13 @@ <string name="zen_modes_dialog_title" msgid="4159138230418567383">"Modos prioritários"</string> <string name="zen_modes_dialog_done" msgid="6654130880256438950">"Concluído"</string> <string name="zen_modes_dialog_settings" msgid="2310248023728936697">"Configurações"</string> - <!-- no translation found for zen_mode_on (9085304934016242591) --> + <string name="zen_mode_on" msgid="9085304934016242591">"Ativado"</string> + <string name="zen_mode_off" msgid="1736604456618147306">"Desativado"</string> + <!-- no translation found for zen_mode_set_up (7457957033034460064) --> <skip /> - <!-- no translation found for zen_mode_off (1736604456618147306) --> + <!-- no translation found for zen_mode_no_manual_invocation (1769975741344633672) --> + <skip /> + <!-- no translation found for zen_mode_active_modes (1625850411578488856) --> <skip /> <string name="zen_priority_introduction" msgid="3159291973383796646">"Você não será perturbado por sons e vibrações, exceto alarmes, lembretes, eventos e chamadas de pessoas especificadas. No entanto, você ouvirá tudo o que decidir reproduzir, como músicas, vídeos e jogos."</string> <string name="zen_alarms_introduction" msgid="3987266042682300470">"Você não será perturbado por sons e vibrações, exceto alarmes. No entanto, você ouvirá tudo o que decidir reproduzir, como músicas, vídeos e jogos."</string> @@ -471,6 +478,8 @@ <string name="keyguard_indication_charging_time_slowly" msgid="301936949731705417">"<xliff:g id="PERCENTAGE">%2$s</xliff:g> • Carga lenta • Conclusão em <xliff:g id="CHARGING_TIME_LEFT">%1$s</xliff:g>"</string> <string name="keyguard_indication_charging_time_dock" msgid="3149328898931741271">"<xliff:g id="PERCENTAGE">%2$s</xliff:g> • Carregando • Conclusão em <xliff:g id="CHARGING_TIME_LEFT">%1$s</xliff:g>"</string> <string name="accessibility_action_open_communal_hub" msgid="3081702792413787849">"Widgets na tela de bloqueio"</string> + <!-- no translation found for accessibility_announcement_communal_widget_added (6911593106099328271) --> + <skip /> <string name="communal_tutorial_indicator_text" msgid="4503010353591430123">"Deslize para a esquerda para iniciar o tutorial compartilhado"</string> <string name="cta_tile_button_to_open_widget_editor" msgid="3871562362382963878">"Personalizar"</string> <string name="cta_tile_button_to_dismiss" msgid="3377597875997861754">"Dispensar"</string> @@ -499,8 +508,7 @@ <string name="accessibility_action_label_place_widget" msgid="1914197458644168978">"posicionar widget selecionado"</string> <string name="communal_widget_picker_title" msgid="1953369090475731663">"Widgets da tela de bloqueio"</string> <string name="communal_widget_picker_description" msgid="490515450110487871">"Todos podem ver os widgets na tela de bloqueio, mesmo com o tablet bloqueado."</string> - <!-- no translation found for accessibility_action_label_unselect_widget (1041811747619468698) --> - <skip /> + <string name="accessibility_action_label_unselect_widget" msgid="1041811747619468698">"desmarcar widget"</string> <string name="communal_widgets_disclaimer_title" msgid="1150954395585308868">"Widgets da tela de bloqueio"</string> <string name="communal_widgets_disclaimer_text" msgid="1423545475160506349">"Para abrir um app usando um widget, você precisará confirmar sua identidade. Além disso, não se esqueça que qualquer pessoa pode ver os widgets, mesmo quando o tablet está bloqueado. Alguns widgets podem não ter sido criados para ficar na tela de bloqueio e fazer isso talvez não seja seguro."</string> <string name="communal_widgets_disclaimer_button" msgid="4423059765740780753">"Entendi"</string> @@ -557,10 +565,8 @@ <string name="media_projection_action_text" msgid="3634906766918186440">"Iniciar agora"</string> <string name="empty_shade_text" msgid="8935967157319717412">"Sem notificações"</string> <string name="no_unseen_notif_text" msgid="395512586119868682">"Nenhuma notificação nova"</string> - <!-- no translation found for adaptive_notification_edu_hun_title (7790738150177329960) --> - <skip /> - <!-- no translation found for adaptive_notification_edu_hun_text (7743367744129536610) --> - <skip /> + <string name="adaptive_notification_edu_hun_title" msgid="7790738150177329960">"O recurso de atenuar notificações está ativo"</string> + <string name="adaptive_notification_edu_hun_text" msgid="7743367744129536610">"Volume e alertas do disp. são reduzidos por até 2 min quando você recebe muitas notificações juntas."</string> <string name="go_to_adaptive_notification_settings" msgid="2423690125178298479">"Desativar"</string> <string name="unlock_to_see_notif_text" msgid="7439033907167561227">"Desbloqueie p/ acessar notificações antigas"</string> <string name="quick_settings_disclosure_parental_controls" msgid="2114102871438223600">"Este dispositivo é gerenciado pelo seu familiar responsável"</string> @@ -1226,7 +1232,6 @@ <string name="accessibility_fingerprint_bouncer" msgid="7189102492498735519">"Autenticação obrigatória. Toque no sensor de impressão digital para autenticar."</string> <string name="ongoing_phone_call_content_description" msgid="5332334388483099947">"Chamada em andamento"</string> <string name="mobile_data_settings_title" msgid="3955246641380064901">"Dados móveis"</string> - <string name="preference_summary_default_combination" msgid="8453246369903749670">"<xliff:g id="STATE">%1$s</xliff:g> / <xliff:g id="NETWORKMODE">%2$s</xliff:g>"</string> <string name="mobile_data_connection_active" msgid="944490013299018227">"Conectado"</string> <string name="mobile_data_temp_connection_active" msgid="4590222725908806824">"Temporariamente conectado"</string> <string name="mobile_data_poor_connection" msgid="819617772268371434">"Conexão fraca"</string> @@ -1380,7 +1385,10 @@ <string name="touchpad_tutorial_done_button" msgid="176168488821755503">"Concluído"</string> <string name="touchpad_tutorial_gesture_done" msgid="4784438360736821255">"Muito bem!"</string> <string name="touchpad_back_gesture_action_title" msgid="7199067250654332735">"Voltar"</string> - <string name="touchpad_back_gesture_guidance" msgid="4222430588599527272">"Para voltar, deslize para a esquerda ou direita usando 3 dedos em qualquer lugar do touchpad."</string> + <!-- no translation found for touchpad_back_gesture_guidance (6263750214998421587) --> + <skip /> + <!-- no translation found for touchpad_back_gesture_finished (5353616006999726249) --> + <skip /> <string name="touchpad_back_gesture_animation_content_description" msgid="2646107450922379918">"Touchpad mostrando 3 dedos deslizando para a direita e esquerda"</string> <string name="touchpad_back_gesture_screen_animation_content_description" msgid="4036267494237748710">"Tela do dispositivo mostrando a animação do gesto de volta"</string> <string name="keyboard_backlight_dialog_title" msgid="8273102932345564724">"Luz de fundo do teclado"</string> @@ -1388,28 +1396,16 @@ <string name="home_controls_dream_label" msgid="6567105701292324257">"Automação residencial"</string> <string name="home_controls_dream_description" msgid="4644150952104035789">"Controles de automação residencial no protetor de tela"</string> <string name="volume_undo_action" msgid="5815519725211877114">"Desfazer"</string> - <!-- no translation found for back_edu_toast_content (4530314597378982956) --> - <skip /> - <!-- no translation found for home_edu_toast_content (3381071147871955415) --> - <skip /> - <!-- no translation found for overview_edu_toast_content (5797030644017804518) --> - <skip /> - <!-- no translation found for all_apps_edu_toast_content (8807496014667211562) --> - <skip /> - <!-- no translation found for back_edu_notification_title (5624780717751357278) --> - <skip /> - <!-- no translation found for back_edu_notification_content (2497557451540954068) --> - <skip /> - <!-- no translation found for home_edu_notification_title (6097902076909654045) --> - <skip /> - <!-- no translation found for home_edu_notification_content (6631697734535766588) --> - <skip /> - <!-- no translation found for overview_edu_notification_title (1265824157319562406) --> - <skip /> - <!-- no translation found for overview_edu_notification_content (3578204677648432500) --> - <skip /> - <!-- no translation found for all_apps_edu_notification_title (372262997265569063) --> - <skip /> - <!-- no translation found for all_apps_edu_notification_content (3255070575694025585) --> - <skip /> + <string name="back_edu_toast_content" msgid="4530314597378982956">"Se quiser voltar, deslize para a esquerda ou direita com três dedos no touchpad"</string> + <string name="home_edu_toast_content" msgid="3381071147871955415">"Se quiser acessar a tela inicial, deslize para cima com três dedos no touchpad"</string> + <string name="overview_edu_toast_content" msgid="5797030644017804518">"Se quiser ver os apps recentes, deslize para cima e pressione com três dedos no touchpad"</string> + <string name="all_apps_edu_toast_content" msgid="8807496014667211562">"Para ver todos os apps, pressione a tecla de ação no teclado"</string> + <string name="back_edu_notification_title" msgid="5624780717751357278">"Use o touchpad para voltar"</string> + <string name="back_edu_notification_content" msgid="2497557451540954068">"Deslize para a esquerda ou direita usando três dedos. Toque para aprender outros gestos."</string> + <string name="home_edu_notification_title" msgid="6097902076909654045">"Use o touchpad para acessar a tela inicial"</string> + <string name="home_edu_notification_content" msgid="6631697734535766588">"Deslize para cima usando três dedos. Toque para aprender outros gestos."</string> + <string name="overview_edu_notification_title" msgid="1265824157319562406">"Use o touchpad para ver os apps recentes"</string> + <string name="overview_edu_notification_content" msgid="3578204677648432500">"Deslize para cima e pressione com três dedos. Toque para aprender outros gestos."</string> + <string name="all_apps_edu_notification_title" msgid="372262997265569063">"Use o teclado para ver todos os apps"</string> + <string name="all_apps_edu_notification_content" msgid="3255070575694025585">"Pressione a tecla de ação a qualquer momento. Toque para aprender outros gestos."</string> </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 097543b8ec06..3526c77d1e24 100644 --- a/packages/SystemUI/res/values-pt-rBR/tiles_states_strings.xml +++ b/packages/SystemUI/res/values-pt-rBR/tiles_states_strings.xml @@ -56,11 +56,6 @@ <item msgid="5376619709702103243">"Desativado"</item> <item msgid="4875147066469902392">"Ativado"</item> </string-array> - <string-array name="tile_states_modes"> - <item msgid="7764936419245199023">"Indisponível"</item> - <item msgid="2004750556637773692">"Desativado"</item> - <item msgid="8968530753931637871">"Ativado"</item> - </string-array> <string-array name="tile_states_flashlight"> <item msgid="3465257127433353857">"Indisponível"</item> <item msgid="5044688398303285224">"Desativada"</item> diff --git a/packages/SystemUI/res/values-pt-rPT/strings.xml b/packages/SystemUI/res/values-pt-rPT/strings.xml index d514a8fbc368..a21f47523820 100644 --- a/packages/SystemUI/res/values-pt-rPT/strings.xml +++ b/packages/SystemUI/res/values-pt-rPT/strings.xml @@ -388,6 +388,9 @@ <string name="performance" msgid="6552785217174378320">"Desempenho"</string> <string name="user_interface" msgid="3712869377953950887">"Interface do utilizador"</string> <string name="thermal" msgid="6758074791325414831">"Térmico"</string> + <string name="custom" msgid="3337456985275158299">"Personalizado"</string> + <string name="custom_trace_settings_dialog_title" msgid="2608570500144830554">"Definições de rastreio personalizadas"</string> + <string name="restore_default" msgid="5259420807486239755">"Restaurar predefinição"</string> <string name="quick_settings_onehanded_label" msgid="2416537930246274991">"Modo para uma mão"</string> <string name="quick_settings_hearing_devices_label" msgid="7277170419679404129">"Disp. auditivos"</string> <string name="quick_settings_hearing_devices_connected" msgid="6519069502397037781">"Ativos"</string> @@ -431,6 +434,12 @@ <string name="zen_modes_dialog_settings" msgid="2310248023728936697">"Definições"</string> <string name="zen_mode_on" msgid="9085304934016242591">"Ativado"</string> <string name="zen_mode_off" msgid="1736604456618147306">"Desativado"</string> + <!-- no translation found for zen_mode_set_up (7457957033034460064) --> + <skip /> + <!-- no translation found for zen_mode_no_manual_invocation (1769975741344633672) --> + <skip /> + <!-- no translation found for zen_mode_active_modes (1625850411578488856) --> + <skip /> <string name="zen_priority_introduction" msgid="3159291973383796646">"Não é incomodado por sons e vibrações, exceto de alarmes, lembretes, eventos e autores de chamadas que especificar. Continua a ouvir tudo o que optar por reproduzir, incluindo música, vídeos e jogos."</string> <string name="zen_alarms_introduction" msgid="3987266042682300470">"Não é incomodado por sons e vibrações, exceto de alarmes. Continua a ouvir tudo o que optar por reproduzir, incluindo música, vídeos e jogos."</string> <string name="zen_priority_customize_button" msgid="4119213187257195047">"Personalizar"</string> @@ -469,6 +478,8 @@ <string name="keyguard_indication_charging_time_slowly" msgid="301936949731705417">"<xliff:g id="PERCENTAGE">%2$s</xliff:g> • A carregar lentamente • Carga completa em <xliff:g id="CHARGING_TIME_LEFT">%1$s</xliff:g>"</string> <string name="keyguard_indication_charging_time_dock" msgid="3149328898931741271">"<xliff:g id="PERCENTAGE">%2$s</xliff:g> • A carregar • Carga completa em <xliff:g id="CHARGING_TIME_LEFT">%1$s</xliff:g>"</string> <string name="accessibility_action_open_communal_hub" msgid="3081702792413787849">"Widgets no ecrã de bloqueio"</string> + <!-- no translation found for accessibility_announcement_communal_widget_added (6911593106099328271) --> + <skip /> <string name="communal_tutorial_indicator_text" msgid="4503010353591430123">"Deslize rapidamente para a esquerda para iniciar o tutorial coletivo"</string> <string name="cta_tile_button_to_open_widget_editor" msgid="3871562362382963878">"Personalizar"</string> <string name="cta_tile_button_to_dismiss" msgid="3377597875997861754">"Ignorar"</string> @@ -554,10 +565,8 @@ <string name="media_projection_action_text" msgid="3634906766918186440">"Começar agora"</string> <string name="empty_shade_text" msgid="8935967157319717412">"Sem notificações"</string> <string name="no_unseen_notif_text" msgid="395512586119868682">"Não existem novas notificações"</string> - <!-- no translation found for adaptive_notification_edu_hun_title (7790738150177329960) --> - <skip /> - <!-- no translation found for adaptive_notification_edu_hun_text (7743367744129536610) --> - <skip /> + <string name="adaptive_notification_edu_hun_title" msgid="7790738150177329960">"O repouso das notificações está ativado"</string> + <string name="adaptive_notification_edu_hun_text" msgid="7743367744129536610">"O volume e os alertas são reduzidos automaticamente durante até 2 minutos quando recebe muitas notificações de uma vez."</string> <string name="go_to_adaptive_notification_settings" msgid="2423690125178298479">"Desativar"</string> <string name="unlock_to_see_notif_text" msgid="7439033907167561227">"Desbloqueie e veja notificações antigas"</string> <string name="quick_settings_disclosure_parental_controls" msgid="2114102871438223600">"Este dispositivo é gerido pelos teus pais"</string> @@ -1223,7 +1232,6 @@ <string name="accessibility_fingerprint_bouncer" msgid="7189102492498735519">"Autenticação necessária. Toque no sensor de impressões digitais para autenticar."</string> <string name="ongoing_phone_call_content_description" msgid="5332334388483099947">"Chamada telefónica em curso"</string> <string name="mobile_data_settings_title" msgid="3955246641380064901">"Dados móveis"</string> - <string name="preference_summary_default_combination" msgid="8453246369903749670">"<xliff:g id="STATE">%1$s</xliff:g>/<xliff:g id="NETWORKMODE">%2$s</xliff:g>"</string> <string name="mobile_data_connection_active" msgid="944490013299018227">"Ligado"</string> <string name="mobile_data_temp_connection_active" msgid="4590222725908806824">"Ligado temporariamente"</string> <string name="mobile_data_poor_connection" msgid="819617772268371434">"Ligação fraca"</string> @@ -1377,7 +1385,10 @@ <string name="touchpad_tutorial_done_button" msgid="176168488821755503">"Concluir"</string> <string name="touchpad_tutorial_gesture_done" msgid="4784438360736821255">"Muito bem!"</string> <string name="touchpad_back_gesture_action_title" msgid="7199067250654332735">"Voltar"</string> - <string name="touchpad_back_gesture_guidance" msgid="4222430588599527272">"Para retroceder, deslize rapidamente para a esquerda ou direita com três dedos em qualquer parte do touchpad."</string> + <!-- no translation found for touchpad_back_gesture_guidance (6263750214998421587) --> + <skip /> + <!-- no translation found for touchpad_back_gesture_finished (5353616006999726249) --> + <skip /> <string name="touchpad_back_gesture_animation_content_description" msgid="2646107450922379918">"Touchpad a mostrar três dedos a moverem-se para a direita e esquerda"</string> <string name="touchpad_back_gesture_screen_animation_content_description" msgid="4036267494237748710">"Ecrã de dispositivo a mostrar uma animação do gesto para retroceder"</string> <string name="keyboard_backlight_dialog_title" msgid="8273102932345564724">"Luz do teclado"</string> 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 d7a245a1fbba..34a5ed7b2ca9 100644 --- a/packages/SystemUI/res/values-pt-rPT/tiles_states_strings.xml +++ b/packages/SystemUI/res/values-pt-rPT/tiles_states_strings.xml @@ -56,11 +56,6 @@ <item msgid="5376619709702103243">"Desligado"</item> <item msgid="4875147066469902392">"Ligado"</item> </string-array> - <string-array name="tile_states_modes"> - <item msgid="7764936419245199023">"Indisponível"</item> - <item msgid="2004750556637773692">"Desativado"</item> - <item msgid="8968530753931637871">"Ativado"</item> - </string-array> <string-array name="tile_states_flashlight"> <item msgid="3465257127433353857">"Indisponível"</item> <item msgid="5044688398303285224">"Desligada"</item> diff --git a/packages/SystemUI/res/values-pt/strings.xml b/packages/SystemUI/res/values-pt/strings.xml index 6a2bc58e2741..e74f57899b3f 100644 --- a/packages/SystemUI/res/values-pt/strings.xml +++ b/packages/SystemUI/res/values-pt/strings.xml @@ -218,7 +218,7 @@ <string name="biometric_re_enroll_notification_content" msgid="8685925877186288180">"Ação necessária para melhorar a segurança e o desempenho"</string> <string name="fingerprint_re_enroll_notification_title" msgid="4539432429683916604">"Configurar o Desbloqueio por impressão digital de novo"</string> <string name="fingerprint_re_enroll_notification_name" msgid="630798657797645704">"Desbloqueio por impressão digital"</string> - <string name="fingerprint_re_enroll_dialog_title" msgid="3526033128113925780">"Configurar o Desbloqueio por impressão digital"</string> + <string name="fingerprint_re_enroll_dialog_title" msgid="3526033128113925780">"Configurar o Desbloqueio por impressão digital"</string> <string name="fingerprint_re_enroll_dialog_content" msgid="4866561176695984879">"Os modelos e as imagens atuais serão excluídos para reconfigurar o Desbloqueio por impressão digital.\n\nDepois disso, você vai precisar configurar esse recurso de novo para desbloquear o smartphone com o dedo ou confirmar sua identidade."</string> <string name="fingerprint_re_enroll_dialog_content_singular" msgid="3083663339787381218">"O modelo e as imagens atuais serão excluídos para reconfigurar o Desbloqueio por impressão digital.\n\nDepois disso, você vai precisar configurar esse recurso de novo para desbloquear o smartphone com o dedo ou confirmar sua identidade."</string> <string name="fingerprint_reenroll_failure_dialog_content" msgid="4733768492747300666">"Não foi possível configurar o Desbloqueio por impressão digital. Acesse as Configurações e tente de novo."</string> @@ -388,6 +388,9 @@ <string name="performance" msgid="6552785217174378320">"Desempenho"</string> <string name="user_interface" msgid="3712869377953950887">"Interface do usuário"</string> <string name="thermal" msgid="6758074791325414831">"Térmico"</string> + <string name="custom" msgid="3337456985275158299">"Personalizado"</string> + <string name="custom_trace_settings_dialog_title" msgid="2608570500144830554">"Configurações de rastreamento personalizado"</string> + <string name="restore_default" msgid="5259420807486239755">"Restaurar padrão"</string> <string name="quick_settings_onehanded_label" msgid="2416537930246274991">"Modo uma mão"</string> <string name="quick_settings_hearing_devices_label" msgid="7277170419679404129">"Aparelhos auditivos"</string> <string name="quick_settings_hearing_devices_connected" msgid="6519069502397037781">"Ativos"</string> @@ -429,9 +432,13 @@ <string name="zen_modes_dialog_title" msgid="4159138230418567383">"Modos prioritários"</string> <string name="zen_modes_dialog_done" msgid="6654130880256438950">"Concluído"</string> <string name="zen_modes_dialog_settings" msgid="2310248023728936697">"Configurações"</string> - <!-- no translation found for zen_mode_on (9085304934016242591) --> + <string name="zen_mode_on" msgid="9085304934016242591">"Ativado"</string> + <string name="zen_mode_off" msgid="1736604456618147306">"Desativado"</string> + <!-- no translation found for zen_mode_set_up (7457957033034460064) --> <skip /> - <!-- no translation found for zen_mode_off (1736604456618147306) --> + <!-- no translation found for zen_mode_no_manual_invocation (1769975741344633672) --> + <skip /> + <!-- no translation found for zen_mode_active_modes (1625850411578488856) --> <skip /> <string name="zen_priority_introduction" msgid="3159291973383796646">"Você não será perturbado por sons e vibrações, exceto alarmes, lembretes, eventos e chamadas de pessoas especificadas. No entanto, você ouvirá tudo o que decidir reproduzir, como músicas, vídeos e jogos."</string> <string name="zen_alarms_introduction" msgid="3987266042682300470">"Você não será perturbado por sons e vibrações, exceto alarmes. No entanto, você ouvirá tudo o que decidir reproduzir, como músicas, vídeos e jogos."</string> @@ -471,6 +478,8 @@ <string name="keyguard_indication_charging_time_slowly" msgid="301936949731705417">"<xliff:g id="PERCENTAGE">%2$s</xliff:g> • Carga lenta • Conclusão em <xliff:g id="CHARGING_TIME_LEFT">%1$s</xliff:g>"</string> <string name="keyguard_indication_charging_time_dock" msgid="3149328898931741271">"<xliff:g id="PERCENTAGE">%2$s</xliff:g> • Carregando • Conclusão em <xliff:g id="CHARGING_TIME_LEFT">%1$s</xliff:g>"</string> <string name="accessibility_action_open_communal_hub" msgid="3081702792413787849">"Widgets na tela de bloqueio"</string> + <!-- no translation found for accessibility_announcement_communal_widget_added (6911593106099328271) --> + <skip /> <string name="communal_tutorial_indicator_text" msgid="4503010353591430123">"Deslize para a esquerda para iniciar o tutorial compartilhado"</string> <string name="cta_tile_button_to_open_widget_editor" msgid="3871562362382963878">"Personalizar"</string> <string name="cta_tile_button_to_dismiss" msgid="3377597875997861754">"Dispensar"</string> @@ -499,8 +508,7 @@ <string name="accessibility_action_label_place_widget" msgid="1914197458644168978">"posicionar widget selecionado"</string> <string name="communal_widget_picker_title" msgid="1953369090475731663">"Widgets da tela de bloqueio"</string> <string name="communal_widget_picker_description" msgid="490515450110487871">"Todos podem ver os widgets na tela de bloqueio, mesmo com o tablet bloqueado."</string> - <!-- no translation found for accessibility_action_label_unselect_widget (1041811747619468698) --> - <skip /> + <string name="accessibility_action_label_unselect_widget" msgid="1041811747619468698">"desmarcar widget"</string> <string name="communal_widgets_disclaimer_title" msgid="1150954395585308868">"Widgets da tela de bloqueio"</string> <string name="communal_widgets_disclaimer_text" msgid="1423545475160506349">"Para abrir um app usando um widget, você precisará confirmar sua identidade. Além disso, não se esqueça que qualquer pessoa pode ver os widgets, mesmo quando o tablet está bloqueado. Alguns widgets podem não ter sido criados para ficar na tela de bloqueio e fazer isso talvez não seja seguro."</string> <string name="communal_widgets_disclaimer_button" msgid="4423059765740780753">"Entendi"</string> @@ -557,10 +565,8 @@ <string name="media_projection_action_text" msgid="3634906766918186440">"Iniciar agora"</string> <string name="empty_shade_text" msgid="8935967157319717412">"Sem notificações"</string> <string name="no_unseen_notif_text" msgid="395512586119868682">"Nenhuma notificação nova"</string> - <!-- no translation found for adaptive_notification_edu_hun_title (7790738150177329960) --> - <skip /> - <!-- no translation found for adaptive_notification_edu_hun_text (7743367744129536610) --> - <skip /> + <string name="adaptive_notification_edu_hun_title" msgid="7790738150177329960">"O recurso de atenuar notificações está ativo"</string> + <string name="adaptive_notification_edu_hun_text" msgid="7743367744129536610">"Volume e alertas do disp. são reduzidos por até 2 min quando você recebe muitas notificações juntas."</string> <string name="go_to_adaptive_notification_settings" msgid="2423690125178298479">"Desativar"</string> <string name="unlock_to_see_notif_text" msgid="7439033907167561227">"Desbloqueie p/ acessar notificações antigas"</string> <string name="quick_settings_disclosure_parental_controls" msgid="2114102871438223600">"Este dispositivo é gerenciado pelo seu familiar responsável"</string> @@ -1226,7 +1232,6 @@ <string name="accessibility_fingerprint_bouncer" msgid="7189102492498735519">"Autenticação obrigatória. Toque no sensor de impressão digital para autenticar."</string> <string name="ongoing_phone_call_content_description" msgid="5332334388483099947">"Chamada em andamento"</string> <string name="mobile_data_settings_title" msgid="3955246641380064901">"Dados móveis"</string> - <string name="preference_summary_default_combination" msgid="8453246369903749670">"<xliff:g id="STATE">%1$s</xliff:g> / <xliff:g id="NETWORKMODE">%2$s</xliff:g>"</string> <string name="mobile_data_connection_active" msgid="944490013299018227">"Conectado"</string> <string name="mobile_data_temp_connection_active" msgid="4590222725908806824">"Temporariamente conectado"</string> <string name="mobile_data_poor_connection" msgid="819617772268371434">"Conexão fraca"</string> @@ -1380,7 +1385,10 @@ <string name="touchpad_tutorial_done_button" msgid="176168488821755503">"Concluído"</string> <string name="touchpad_tutorial_gesture_done" msgid="4784438360736821255">"Muito bem!"</string> <string name="touchpad_back_gesture_action_title" msgid="7199067250654332735">"Voltar"</string> - <string name="touchpad_back_gesture_guidance" msgid="4222430588599527272">"Para voltar, deslize para a esquerda ou direita usando 3 dedos em qualquer lugar do touchpad."</string> + <!-- no translation found for touchpad_back_gesture_guidance (6263750214998421587) --> + <skip /> + <!-- no translation found for touchpad_back_gesture_finished (5353616006999726249) --> + <skip /> <string name="touchpad_back_gesture_animation_content_description" msgid="2646107450922379918">"Touchpad mostrando 3 dedos deslizando para a direita e esquerda"</string> <string name="touchpad_back_gesture_screen_animation_content_description" msgid="4036267494237748710">"Tela do dispositivo mostrando a animação do gesto de volta"</string> <string name="keyboard_backlight_dialog_title" msgid="8273102932345564724">"Luz de fundo do teclado"</string> @@ -1388,28 +1396,16 @@ <string name="home_controls_dream_label" msgid="6567105701292324257">"Automação residencial"</string> <string name="home_controls_dream_description" msgid="4644150952104035789">"Controles de automação residencial no protetor de tela"</string> <string name="volume_undo_action" msgid="5815519725211877114">"Desfazer"</string> - <!-- no translation found for back_edu_toast_content (4530314597378982956) --> - <skip /> - <!-- no translation found for home_edu_toast_content (3381071147871955415) --> - <skip /> - <!-- no translation found for overview_edu_toast_content (5797030644017804518) --> - <skip /> - <!-- no translation found for all_apps_edu_toast_content (8807496014667211562) --> - <skip /> - <!-- no translation found for back_edu_notification_title (5624780717751357278) --> - <skip /> - <!-- no translation found for back_edu_notification_content (2497557451540954068) --> - <skip /> - <!-- no translation found for home_edu_notification_title (6097902076909654045) --> - <skip /> - <!-- no translation found for home_edu_notification_content (6631697734535766588) --> - <skip /> - <!-- no translation found for overview_edu_notification_title (1265824157319562406) --> - <skip /> - <!-- no translation found for overview_edu_notification_content (3578204677648432500) --> - <skip /> - <!-- no translation found for all_apps_edu_notification_title (372262997265569063) --> - <skip /> - <!-- no translation found for all_apps_edu_notification_content (3255070575694025585) --> - <skip /> + <string name="back_edu_toast_content" msgid="4530314597378982956">"Se quiser voltar, deslize para a esquerda ou direita com três dedos no touchpad"</string> + <string name="home_edu_toast_content" msgid="3381071147871955415">"Se quiser acessar a tela inicial, deslize para cima com três dedos no touchpad"</string> + <string name="overview_edu_toast_content" msgid="5797030644017804518">"Se quiser ver os apps recentes, deslize para cima e pressione com três dedos no touchpad"</string> + <string name="all_apps_edu_toast_content" msgid="8807496014667211562">"Para ver todos os apps, pressione a tecla de ação no teclado"</string> + <string name="back_edu_notification_title" msgid="5624780717751357278">"Use o touchpad para voltar"</string> + <string name="back_edu_notification_content" msgid="2497557451540954068">"Deslize para a esquerda ou direita usando três dedos. Toque para aprender outros gestos."</string> + <string name="home_edu_notification_title" msgid="6097902076909654045">"Use o touchpad para acessar a tela inicial"</string> + <string name="home_edu_notification_content" msgid="6631697734535766588">"Deslize para cima usando três dedos. Toque para aprender outros gestos."</string> + <string name="overview_edu_notification_title" msgid="1265824157319562406">"Use o touchpad para ver os apps recentes"</string> + <string name="overview_edu_notification_content" msgid="3578204677648432500">"Deslize para cima e pressione com três dedos. Toque para aprender outros gestos."</string> + <string name="all_apps_edu_notification_title" msgid="372262997265569063">"Use o teclado para ver todos os apps"</string> + <string name="all_apps_edu_notification_content" msgid="3255070575694025585">"Pressione a tecla de ação a qualquer momento. Toque para aprender outros gestos."</string> </resources> diff --git a/packages/SystemUI/res/values-pt/tiles_states_strings.xml b/packages/SystemUI/res/values-pt/tiles_states_strings.xml index 097543b8ec06..3526c77d1e24 100644 --- a/packages/SystemUI/res/values-pt/tiles_states_strings.xml +++ b/packages/SystemUI/res/values-pt/tiles_states_strings.xml @@ -56,11 +56,6 @@ <item msgid="5376619709702103243">"Desativado"</item> <item msgid="4875147066469902392">"Ativado"</item> </string-array> - <string-array name="tile_states_modes"> - <item msgid="7764936419245199023">"Indisponível"</item> - <item msgid="2004750556637773692">"Desativado"</item> - <item msgid="8968530753931637871">"Ativado"</item> - </string-array> <string-array name="tile_states_flashlight"> <item msgid="3465257127433353857">"Indisponível"</item> <item msgid="5044688398303285224">"Desativada"</item> diff --git a/packages/SystemUI/res/values-ro/strings.xml b/packages/SystemUI/res/values-ro/strings.xml index b129e5137715..d0895ada88f7 100644 --- a/packages/SystemUI/res/values-ro/strings.xml +++ b/packages/SystemUI/res/values-ro/strings.xml @@ -388,6 +388,9 @@ <string name="performance" msgid="6552785217174378320">"Performanță"</string> <string name="user_interface" msgid="3712869377953950887">"Interfața de utilizare"</string> <string name="thermal" msgid="6758074791325414831">"Termal"</string> + <string name="custom" msgid="3337456985275158299">"Personalizat"</string> + <string name="custom_trace_settings_dialog_title" msgid="2608570500144830554">"Setări de urmărire personalizate"</string> + <string name="restore_default" msgid="5259420807486239755">"Revino la valoarea prestabilită"</string> <string name="quick_settings_onehanded_label" msgid="2416537930246274991">"Modul cu o mână"</string> <string name="quick_settings_hearing_devices_label" msgid="7277170419679404129">"Aparate auditive"</string> <string name="quick_settings_hearing_devices_connected" msgid="6519069502397037781">"Activ"</string> @@ -429,9 +432,13 @@ <string name="zen_modes_dialog_title" msgid="4159138230418567383">"Moduri cu prioritate"</string> <string name="zen_modes_dialog_done" msgid="6654130880256438950">"Gata"</string> <string name="zen_modes_dialog_settings" msgid="2310248023728936697">"Setări"</string> - <!-- no translation found for zen_mode_on (9085304934016242591) --> + <string name="zen_mode_on" msgid="9085304934016242591">"Activat"</string> + <string name="zen_mode_off" msgid="1736604456618147306">"Dezactivat"</string> + <!-- no translation found for zen_mode_set_up (7457957033034460064) --> <skip /> - <!-- no translation found for zen_mode_off (1736604456618147306) --> + <!-- no translation found for zen_mode_no_manual_invocation (1769975741344633672) --> + <skip /> + <!-- no translation found for zen_mode_active_modes (1625850411578488856) --> <skip /> <string name="zen_priority_introduction" msgid="3159291973383796646">"Se vor anunța prin sunete și vibrații numai alarmele, mementourile, evenimentele și apelanții specificați de tine. Totuși, vei auzi tot ce alegi să redai, inclusiv muzică, videoclipuri și jocuri."</string> <string name="zen_alarms_introduction" msgid="3987266042682300470">"Se vor anunța prin sunete și vibrații numai alarmele. Totuși, vei auzi tot ce alegi să redai, inclusiv muzică, videoclipuri și jocuri."</string> @@ -471,6 +478,8 @@ <string name="keyguard_indication_charging_time_slowly" msgid="301936949731705417">"<xliff:g id="PERCENTAGE">%2$s</xliff:g> • Se încarcă lent • <xliff:g id="CHARGING_TIME_LEFT">%1$s</xliff:g> până la încărcarea completă"</string> <string name="keyguard_indication_charging_time_dock" msgid="3149328898931741271">"<xliff:g id="PERCENTAGE">%2$s</xliff:g> • Se încarcă • <xliff:g id="CHARGING_TIME_LEFT">%1$s</xliff:g> până la încărcarea completă"</string> <string name="accessibility_action_open_communal_hub" msgid="3081702792413787849">"Widgeturi pe ecranul de blocare"</string> + <!-- no translation found for accessibility_announcement_communal_widget_added (6911593106099328271) --> + <skip /> <string name="communal_tutorial_indicator_text" msgid="4503010353591430123">"Glisează spre stânga pentru a începe tutorialul pentru comunitate"</string> <string name="cta_tile_button_to_open_widget_editor" msgid="3871562362382963878">"Personalizează"</string> <string name="cta_tile_button_to_dismiss" msgid="3377597875997861754">"Respinge"</string> @@ -499,8 +508,7 @@ <string name="accessibility_action_label_place_widget" msgid="1914197458644168978">"plasează widgetul selectat"</string> <string name="communal_widget_picker_title" msgid="1953369090475731663">"Widgeturi pe ecranul de blocare"</string> <string name="communal_widget_picker_description" msgid="490515450110487871">"Oricine vede widgeturile pe ecranul de blocare, chiar dacă tableta e blocată"</string> - <!-- no translation found for accessibility_action_label_unselect_widget (1041811747619468698) --> - <skip /> + <string name="accessibility_action_label_unselect_widget" msgid="1041811747619468698">"deselectează widgetul"</string> <string name="communal_widgets_disclaimer_title" msgid="1150954395585308868">"Widgeturi pe ecranul de blocare"</string> <string name="communal_widgets_disclaimer_text" msgid="1423545475160506349">"Pentru a deschide o aplicație folosind un widget, va trebui să-ți confirmi identitatea. În plus, reține că oricine poate să vadă widgeturile, chiar dacă tableta este blocată. Este posibil ca unele widgeturi să nu fi fost create pentru ecranul de blocare și poate fi nesigur să le adaugi aici."</string> <string name="communal_widgets_disclaimer_button" msgid="4423059765740780753">"OK"</string> @@ -557,10 +565,8 @@ <string name="media_projection_action_text" msgid="3634906766918186440">"Începe acum"</string> <string name="empty_shade_text" msgid="8935967157319717412">"Nicio notificare"</string> <string name="no_unseen_notif_text" msgid="395512586119868682">"Nicio notificare nouă"</string> - <!-- no translation found for adaptive_notification_edu_hun_title (7790738150177329960) --> - <skip /> - <!-- no translation found for adaptive_notification_edu_hun_text (7743367744129536610) --> - <skip /> + <string name="adaptive_notification_edu_hun_title" msgid="7790738150177329960">"Reducerea sunetului notificărilor este activată"</string> + <string name="adaptive_notification_edu_hun_text" msgid="7743367744129536610">"Volumul și alertele dispozitivului sunt reduse automat timp de până la 2 min. când primești prea multe notificări odată"</string> <string name="go_to_adaptive_notification_settings" msgid="2423690125178298479">"Dezactivează"</string> <string name="unlock_to_see_notif_text" msgid="7439033907167561227">"Deblochează ca să vezi notificări vechi"</string> <string name="quick_settings_disclosure_parental_controls" msgid="2114102871438223600">"Dispozitivul este gestionat de unul dintre părinți"</string> @@ -1226,7 +1232,6 @@ <string name="accessibility_fingerprint_bouncer" msgid="7189102492498735519">"Autentificare obligatorie. Atinge senzorul de amprentă pentru a te autentifica."</string> <string name="ongoing_phone_call_content_description" msgid="5332334388483099947">"Apel telefonic în desfășurare"</string> <string name="mobile_data_settings_title" msgid="3955246641380064901">"Date mobile"</string> - <string name="preference_summary_default_combination" msgid="8453246369903749670">"<xliff:g id="STATE">%1$s</xliff:g>/<xliff:g id="NETWORKMODE">%2$s</xliff:g>"</string> <string name="mobile_data_connection_active" msgid="944490013299018227">"Conectat"</string> <string name="mobile_data_temp_connection_active" msgid="4590222725908806824">"Conectat temporar"</string> <string name="mobile_data_poor_connection" msgid="819617772268371434">"Conexiune slabă"</string> @@ -1380,7 +1385,10 @@ <string name="touchpad_tutorial_done_button" msgid="176168488821755503">"Gata"</string> <string name="touchpad_tutorial_gesture_done" msgid="4784438360736821255">"Excelent!"</string> <string name="touchpad_back_gesture_action_title" msgid="7199067250654332735">"Înapoi"</string> - <string name="touchpad_back_gesture_guidance" msgid="4222430588599527272">"Pentru a reveni, glisează spre stânga sau spre dreapta cu trei degete oriunde pe touchpad."</string> + <!-- no translation found for touchpad_back_gesture_guidance (6263750214998421587) --> + <skip /> + <!-- no translation found for touchpad_back_gesture_finished (5353616006999726249) --> + <skip /> <string name="touchpad_back_gesture_animation_content_description" msgid="2646107450922379918">"Touchpad cu trei degete care se mișcă spre dreapta și spre stânga"</string> <string name="touchpad_back_gesture_screen_animation_content_description" msgid="4036267494237748710">"Ecran de dispozitiv cu o animație pentru gestul Înapoi"</string> <string name="keyboard_backlight_dialog_title" msgid="8273102932345564724">"Iluminarea din spate a tastaturii"</string> @@ -1388,28 +1396,16 @@ <string name="home_controls_dream_label" msgid="6567105701292324257">"Comenzi pentru locuință"</string> <string name="home_controls_dream_description" msgid="4644150952104035789">"Accesează comenzile pentru locuință ca screensaver"</string> <string name="volume_undo_action" msgid="5815519725211877114">"Anulează"</string> - <!-- no translation found for back_edu_toast_content (4530314597378982956) --> - <skip /> - <!-- no translation found for home_edu_toast_content (3381071147871955415) --> - <skip /> - <!-- no translation found for overview_edu_toast_content (5797030644017804518) --> - <skip /> - <!-- no translation found for all_apps_edu_toast_content (8807496014667211562) --> - <skip /> - <!-- no translation found for back_edu_notification_title (5624780717751357278) --> - <skip /> - <!-- no translation found for back_edu_notification_content (2497557451540954068) --> - <skip /> - <!-- no translation found for home_edu_notification_title (6097902076909654045) --> - <skip /> - <!-- no translation found for home_edu_notification_content (6631697734535766588) --> - <skip /> - <!-- no translation found for overview_edu_notification_title (1265824157319562406) --> - <skip /> - <!-- no translation found for overview_edu_notification_content (3578204677648432500) --> - <skip /> - <!-- no translation found for all_apps_edu_notification_title (372262997265569063) --> - <skip /> - <!-- no translation found for all_apps_edu_notification_content (3255070575694025585) --> - <skip /> + <string name="back_edu_toast_content" msgid="4530314597378982956">"Pentru a reveni, glisează spre stânga sau spre dreapta cu trei degete pe touchpad"</string> + <string name="home_edu_toast_content" msgid="3381071147871955415">"Ca să accesezi pagina de pornire, glisează în sus cu trei degete pe touchpad"</string> + <string name="overview_edu_toast_content" msgid="5797030644017804518">"Ca să vezi aplicațiile recente, glisează în sus și ține apăsat cu trei degete pe touchpad"</string> + <string name="all_apps_edu_toast_content" msgid="8807496014667211562">"Ca să vezi toate aplicațiile, apasă tasta de acțiuni de pe tastatură"</string> + <string name="back_edu_notification_title" msgid="5624780717751357278">"Folosește-ți touchpadul ca să revii"</string> + <string name="back_edu_notification_content" msgid="2497557451540954068">"Glisează la stânga sau la dreapta cu trei degete. Atinge ca să înveți mai multe gesturi."</string> + <string name="home_edu_notification_title" msgid="6097902076909654045">"Folosește-ți touchpadul ca să accesezi pagina de pornire"</string> + <string name="home_edu_notification_content" msgid="6631697734535766588">"Glisează în sus cu trei degete. Atinge ca să înveți mai multe gesturi."</string> + <string name="overview_edu_notification_title" msgid="1265824157319562406">"Folosește-ți touchpadul ca să vezi aplicațiile recente"</string> + <string name="overview_edu_notification_content" msgid="3578204677648432500">"Glisează în sus și ține apăsat cu trei degete. Atinge ca să înveți mai multe gesturi."</string> + <string name="all_apps_edu_notification_title" msgid="372262997265569063">"Folosește-ți tastatura ca să vezi toate aplicațiile"</string> + <string name="all_apps_edu_notification_content" msgid="3255070575694025585">"Apasă oricând tasta de acțiuni. Atinge ca să înveți mai multe gesturi."</string> </resources> diff --git a/packages/SystemUI/res/values-ro/tiles_states_strings.xml b/packages/SystemUI/res/values-ro/tiles_states_strings.xml index 22b50709dee7..a68f1408dd83 100644 --- a/packages/SystemUI/res/values-ro/tiles_states_strings.xml +++ b/packages/SystemUI/res/values-ro/tiles_states_strings.xml @@ -56,11 +56,6 @@ <item msgid="5376619709702103243">"Dezactivată"</item> <item msgid="4875147066469902392">"Activată"</item> </string-array> - <string-array name="tile_states_modes"> - <item msgid="7764936419245199023">"Indisponibil"</item> - <item msgid="2004750556637773692">"Dezactivat"</item> - <item msgid="8968530753931637871">"Activat"</item> - </string-array> <string-array name="tile_states_flashlight"> <item msgid="3465257127433353857">"Indisponibilă"</item> <item msgid="5044688398303285224">"Dezactivată"</item> diff --git a/packages/SystemUI/res/values-ru/strings.xml b/packages/SystemUI/res/values-ru/strings.xml index ebbac593504e..3811185f62d3 100644 --- a/packages/SystemUI/res/values-ru/strings.xml +++ b/packages/SystemUI/res/values-ru/strings.xml @@ -119,7 +119,7 @@ <string name="screenrecord_continue" msgid="4055347133700593164">"Начать"</string> <string name="screenrecord_ongoing_screen_only" msgid="4459670242451527727">"Идет запись видео с экрана"</string> <string name="screenrecord_ongoing_screen_and_audio" msgid="5351133763125180920">"Идет запись видео с экрана и звука"</string> - <string name="screenrecord_taps_label" msgid="1595690528298857649">"Показывать прикосновения к экрану"</string> + <string name="screenrecord_taps_label" msgid="1595690528298857649">"Показывать прикосновения"</string> <string name="screenrecord_stop_label" msgid="72699670052087989">"Остановить"</string> <string name="screenrecord_share_label" msgid="5025590804030086930">"Поделиться"</string> <string name="screenrecord_save_title" msgid="1886652605520893850">"Видео с экрана сохранено"</string> @@ -378,7 +378,7 @@ <string name="quick_settings_screen_record_label" msgid="8650355346742003694">"Запись видео с экрана"</string> <string name="quick_settings_screen_record_start" msgid="1574725369331638985">"Начать"</string> <string name="quick_settings_screen_record_stop" msgid="8087348522976412119">"Остановить"</string> - <string name="qs_record_issue_label" msgid="8166290137285529059">"Запись неисправности"</string> + <string name="qs_record_issue_label" msgid="8166290137285529059">"Запись неполадки"</string> <string name="qs_record_issue_start" msgid="2979831312582567056">"Начать"</string> <string name="qs_record_issue_stop" msgid="3531747965741982657">"Остановить"</string> <string name="qs_record_issue_bug_report" msgid="8229031766918650079">"Отчет об ошибке"</string> @@ -387,7 +387,10 @@ <string name="qs_record_issue_dropdown_screenrecord" msgid="6396141928484257626">"Запись экрана"</string> <string name="performance" msgid="6552785217174378320">"Производительность"</string> <string name="user_interface" msgid="3712869377953950887">"Интерфейс"</string> - <string name="thermal" msgid="6758074791325414831">"Тепловизор"</string> + <string name="thermal" msgid="6758074791325414831">"Нагрев"</string> + <string name="custom" msgid="3337456985275158299">"Свой вариант"</string> + <string name="custom_trace_settings_dialog_title" msgid="2608570500144830554">"Свои настройки трассировки"</string> + <string name="restore_default" msgid="5259420807486239755">"Восстановить настройки по умолчанию"</string> <string name="quick_settings_onehanded_label" msgid="2416537930246274991">"Режим управления одной рукой"</string> <string name="quick_settings_hearing_devices_label" msgid="7277170419679404129">"Слуховые аппараты"</string> <string name="quick_settings_hearing_devices_connected" msgid="6519069502397037781">"Активно"</string> @@ -429,9 +432,13 @@ <string name="zen_modes_dialog_title" msgid="4159138230418567383">"Режимы приоритета"</string> <string name="zen_modes_dialog_done" msgid="6654130880256438950">"Готово"</string> <string name="zen_modes_dialog_settings" msgid="2310248023728936697">"Настройки"</string> - <!-- no translation found for zen_mode_on (9085304934016242591) --> + <string name="zen_mode_on" msgid="9085304934016242591">"Включено"</string> + <string name="zen_mode_off" msgid="1736604456618147306">"Отключено"</string> + <!-- no translation found for zen_mode_set_up (7457957033034460064) --> <skip /> - <!-- no translation found for zen_mode_off (1736604456618147306) --> + <!-- no translation found for zen_mode_no_manual_invocation (1769975741344633672) --> + <skip /> + <!-- no translation found for zen_mode_active_modes (1625850411578488856) --> <skip /> <string name="zen_priority_introduction" msgid="3159291973383796646">"Вас не будут отвлекать звуки и вибрация, за исключением сигналов будильника, напоминаний, уведомлений о мероприятиях и звонков от помеченных контактов. Вы по-прежнему будете слышать включенную вами музыку, видео, игры и т. д."</string> <string name="zen_alarms_introduction" msgid="3987266042682300470">"Вас не будут отвлекать звуки и вибрация, за исключением сигналов будильника. Вы по-прежнему будете слышать включенную вами музыку, видео, игры и т. д."</string> @@ -471,6 +478,8 @@ <string name="keyguard_indication_charging_time_slowly" msgid="301936949731705417">"<xliff:g id="PERCENTAGE">%2$s</xliff:g> • Медленная зарядка • Осталось <xliff:g id="CHARGING_TIME_LEFT">%1$s</xliff:g>"</string> <string name="keyguard_indication_charging_time_dock" msgid="3149328898931741271">"<xliff:g id="PERCENTAGE">%2$s</xliff:g> • Зарядка • Осталось <xliff:g id="CHARGING_TIME_LEFT">%1$s</xliff:g>"</string> <string name="accessibility_action_open_communal_hub" msgid="3081702792413787849">"Виджеты на заблокированном экране"</string> + <!-- no translation found for accessibility_announcement_communal_widget_added (6911593106099328271) --> + <skip /> <string name="communal_tutorial_indicator_text" msgid="4503010353591430123">"Чтобы ознакомиться с руководством, проведите по экрану влево"</string> <string name="cta_tile_button_to_open_widget_editor" msgid="3871562362382963878">"Настроить"</string> <string name="cta_tile_button_to_dismiss" msgid="3377597875997861754">"Закрыть"</string> @@ -499,8 +508,7 @@ <string name="accessibility_action_label_place_widget" msgid="1914197458644168978">"разместить выбранный виджет"</string> <string name="communal_widget_picker_title" msgid="1953369090475731663">"Виджеты на заблокированном экране"</string> <string name="communal_widget_picker_description" msgid="490515450110487871">"Они видны всем, даже если планшет заблокирован."</string> - <!-- no translation found for accessibility_action_label_unselect_widget (1041811747619468698) --> - <skip /> + <string name="accessibility_action_label_unselect_widget" msgid="1041811747619468698">"отменить выбор виджета"</string> <string name="communal_widgets_disclaimer_title" msgid="1150954395585308868">"Виджеты на заблокированном экране"</string> <string name="communal_widgets_disclaimer_text" msgid="1423545475160506349">"Чтобы открыть приложение, используя виджет, вам нужно будет подтвердить свою личность. Обратите внимание, что виджеты видны всем, даже если планшет заблокирован. Некоторые виджеты не предназначены для использования на заблокированном экране. Добавлять их туда может быть небезопасно."</string> <string name="communal_widgets_disclaimer_button" msgid="4423059765740780753">"ОК"</string> @@ -557,10 +565,8 @@ <string name="media_projection_action_text" msgid="3634906766918186440">"Начать"</string> <string name="empty_shade_text" msgid="8935967157319717412">"Нет уведомлений."</string> <string name="no_unseen_notif_text" msgid="395512586119868682">"Новых уведомлений нет"</string> - <!-- no translation found for adaptive_notification_edu_hun_title (7790738150177329960) --> - <skip /> - <!-- no translation found for adaptive_notification_edu_hun_text (7743367744129536610) --> - <skip /> + <string name="adaptive_notification_edu_hun_title" msgid="7790738150177329960">"Снижение громкости уведомлений включено"</string> + <string name="adaptive_notification_edu_hun_text" msgid="7743367744129536610">"Если придет слишком много уведомлений, на две минуты громкость и количество оповещений уменьшатся."</string> <string name="go_to_adaptive_notification_settings" msgid="2423690125178298479">"Отключить"</string> <string name="unlock_to_see_notif_text" msgid="7439033907167561227">"Разблокируйте, чтобы увидеть уведомления"</string> <string name="quick_settings_disclosure_parental_controls" msgid="2114102871438223600">"Устройством управляет один из родителей."</string> @@ -659,7 +665,7 @@ <string name="volume_stream_content_description_mute" msgid="4079046784917920984">"%1$s. Нажмите, чтобы выключить звук. Специальные возможности могут прекратить работу."</string> <string name="volume_stream_content_description_vibrate_a11y" msgid="2742330052979397471">"%1$s. Нажмите, чтобы включить вибрацию."</string> <string name="volume_stream_content_description_mute_a11y" msgid="5743548478357238156">"%1$s. Нажмите, чтобы выключить звук."</string> - <string name="volume_panel_noise_control_title" msgid="7413949943872304474">"Контроль уровня шума"</string> + <string name="volume_panel_noise_control_title" msgid="7413949943872304474">"Контроль шума"</string> <string name="volume_panel_spatial_audio_title" msgid="3367048857932040660">"Пространственное звучание"</string> <string name="volume_panel_spatial_audio_off" msgid="4177490084606772989">"Отключено"</string> <string name="volume_panel_spatial_audio_fixed" msgid="3136080137827746046">"Без отслеживания"</string> @@ -677,8 +683,8 @@ <string name="volume_panel_hint_unmute" msgid="4831850937582282340">"Включить звук аудиопотока \"%s\""</string> <string name="volume_panel_hint_muted" msgid="1124844870181285320">"без звука"</string> <string name="volume_panel_hint_vibrate" msgid="4136223145435914132">"вибросигнал"</string> - <string name="media_output_label_title" msgid="872824698593182505">"<xliff:g id="LABEL">%s</xliff:g> – запущено здесь:"</string> - <string name="media_output_title_without_playing" msgid="3825663683169305013">"Проигрывание аудио:"</string> + <string name="media_output_label_title" msgid="872824698593182505">"<xliff:g id="LABEL">%s</xliff:g> – играет здесь:"</string> + <string name="media_output_title_without_playing" msgid="3825663683169305013">"Аудио будет звучать здесь"</string> <string name="media_output_title_ongoing_call" msgid="208426888064112006">"Настройки вызова"</string> <string name="system_ui_tuner" msgid="1471348823289954729">"System UI Tuner"</string> <string name="status_bar" msgid="4357390266055077437">"Строка состояния"</string> @@ -735,7 +741,7 @@ <string name="notification_channel_summary_automatic_silenced" msgid="7403004439649872047">"<b>Статус:</b> понижено до уровня \"Без звука\""</string> <string name="notification_channel_summary_automatic_promoted" msgid="1301710305149590426">"<b>Статус:</b> уровень важности повышен"</string> <string name="notification_channel_summary_automatic_demoted" msgid="1831303964660807700">"<b>Статус:</b> уровень важности понижен"</string> - <string name="notification_channel_summary_priority_baseline" msgid="46674690072551234">"Появляется в верхней части уведомлений о сообщениях, а также в качестве фото профиля на заблокированном экране"</string> + <string name="notification_channel_summary_priority_baseline" msgid="46674690072551234">"Вверху списка уведомлений о разговорах и в виде фото профиля на заблокированном экране"</string> <string name="notification_channel_summary_priority_bubble" msgid="1275413109619074576">"Появляется в верхней части уведомлений о сообщениях, в виде всплывающего чата, а также в качестве фото профиля на заблокированном экране."</string> <string name="notification_channel_summary_priority_dnd" msgid="6665395023264154361">"Появляется в верхней части уведомлений о сообщениях, а также в виде фото профиля на заблокированном экране, прерывает режим \"Не беспокоить\"."</string> <string name="notification_channel_summary_priority_all" msgid="7151752959650048285">"Появляется в верхней части уведомлений о сообщениях, в виде всплывающего чата, а также в качестве фото профиля на заблокированном экране, прерывает режим \"Не беспокоить\"."</string> @@ -1226,7 +1232,6 @@ <string name="accessibility_fingerprint_bouncer" msgid="7189102492498735519">"Требуется аутентификация. Приложите палец к сканеру отпечатков."</string> <string name="ongoing_phone_call_content_description" msgid="5332334388483099947">"Текущий вызов"</string> <string name="mobile_data_settings_title" msgid="3955246641380064901">"Мобильный интернет"</string> - <string name="preference_summary_default_combination" msgid="8453246369903749670">"<xliff:g id="STATE">%1$s</xliff:g>/<xliff:g id="NETWORKMODE">%2$s</xliff:g>"</string> <string name="mobile_data_connection_active" msgid="944490013299018227">"Подключено"</string> <string name="mobile_data_temp_connection_active" msgid="4590222725908806824">"Временное подключение"</string> <string name="mobile_data_poor_connection" msgid="819617772268371434">"Слабый сигнал"</string> @@ -1380,7 +1385,10 @@ <string name="touchpad_tutorial_done_button" msgid="176168488821755503">"Готово"</string> <string name="touchpad_tutorial_gesture_done" msgid="4784438360736821255">"Отлично!"</string> <string name="touchpad_back_gesture_action_title" msgid="7199067250654332735">"Назад"</string> - <string name="touchpad_back_gesture_guidance" msgid="4222430588599527272">"Чтобы вернуться, проведите тремя пальцами влево или вправо по сенсорной панели."</string> + <!-- no translation found for touchpad_back_gesture_guidance (6263750214998421587) --> + <skip /> + <!-- no translation found for touchpad_back_gesture_finished (5353616006999726249) --> + <skip /> <string name="touchpad_back_gesture_animation_content_description" msgid="2646107450922379918">"Три пальца двигаются вправо и влево по сенсорной панели"</string> <string name="touchpad_back_gesture_screen_animation_content_description" msgid="4036267494237748710">"На экране устройства показана анимация для жеста \"Назад\""</string> <string name="keyboard_backlight_dialog_title" msgid="8273102932345564724">"Подсветка клавиатуры"</string> @@ -1388,28 +1396,16 @@ <string name="home_controls_dream_label" msgid="6567105701292324257">"Управление домом"</string> <string name="home_controls_dream_description" msgid="4644150952104035789">"Быстрый доступ к управлению домом через заставку"</string> <string name="volume_undo_action" msgid="5815519725211877114">"Отменить"</string> - <!-- no translation found for back_edu_toast_content (4530314597378982956) --> - <skip /> - <!-- no translation found for home_edu_toast_content (3381071147871955415) --> - <skip /> - <!-- no translation found for overview_edu_toast_content (5797030644017804518) --> - <skip /> - <!-- no translation found for all_apps_edu_toast_content (8807496014667211562) --> - <skip /> - <!-- no translation found for back_edu_notification_title (5624780717751357278) --> - <skip /> - <!-- no translation found for back_edu_notification_content (2497557451540954068) --> - <skip /> - <!-- no translation found for home_edu_notification_title (6097902076909654045) --> - <skip /> - <!-- no translation found for home_edu_notification_content (6631697734535766588) --> - <skip /> - <!-- no translation found for overview_edu_notification_title (1265824157319562406) --> - <skip /> - <!-- no translation found for overview_edu_notification_content (3578204677648432500) --> - <skip /> - <!-- no translation found for all_apps_edu_notification_title (372262997265569063) --> - <skip /> - <!-- no translation found for all_apps_edu_notification_content (3255070575694025585) --> - <skip /> + <string name="back_edu_toast_content" msgid="4530314597378982956">"Чтобы вернуться назад, проведите по сенсорной панели тремя пальцами влево или вправо."</string> + <string name="home_edu_toast_content" msgid="3381071147871955415">"Чтобы перейти на главный экран, проведите по сенсорной панели тремя пальцами вверх."</string> + <string name="overview_edu_toast_content" msgid="5797030644017804518">"Чтобы увидеть недавние приложения, проведите по сенсорной панели тремя пальцами вверх и удерживайте."</string> + <string name="all_apps_edu_toast_content" msgid="8807496014667211562">"Чтобы открыть список всех своих приложений, нажмите клавишу действия."</string> + <string name="back_edu_notification_title" msgid="5624780717751357278">"Используйте сенсорную панель, чтобы возвращаться назад"</string> + <string name="back_edu_notification_content" msgid="2497557451540954068">"Для этого проведите тремя пальцами влево или вправо. Нажмите, чтобы посмотреть другие жесты."</string> + <string name="home_edu_notification_title" msgid="6097902076909654045">"Используйте сенсорную панель, чтобы переходить на главный экран"</string> + <string name="home_edu_notification_content" msgid="6631697734535766588">"Для этого проведите тремя пальцами вверх. Нажмите, чтобы посмотреть другие жесты."</string> + <string name="overview_edu_notification_title" msgid="1265824157319562406">"Используйте сенсорную панель, чтобы смотреть список недавних приложений"</string> + <string name="overview_edu_notification_content" msgid="3578204677648432500">"Для этого проведите тремя пальцами вверх и удерживайте. Нажмите, чтобы посмотреть другие жесты."</string> + <string name="all_apps_edu_notification_title" msgid="372262997265569063">"Открывайте список всех приложений с помощью клавиатуры"</string> + <string name="all_apps_edu_notification_content" msgid="3255070575694025585">"Для этого можно использовать клавишу действия. Нажмите, чтобы посмотреть другие жесты."</string> </resources> diff --git a/packages/SystemUI/res/values-ru/tiles_states_strings.xml b/packages/SystemUI/res/values-ru/tiles_states_strings.xml index 4d4f39ee98ea..592937c7b9f6 100644 --- a/packages/SystemUI/res/values-ru/tiles_states_strings.xml +++ b/packages/SystemUI/res/values-ru/tiles_states_strings.xml @@ -56,11 +56,6 @@ <item msgid="5376619709702103243">"Откл."</item> <item msgid="4875147066469902392">"Вкл."</item> </string-array> - <string-array name="tile_states_modes"> - <item msgid="7764936419245199023">"Недоступно"</item> - <item msgid="2004750556637773692">"Отключено"</item> - <item msgid="8968530753931637871">"Включено"</item> - </string-array> <string-array name="tile_states_flashlight"> <item msgid="3465257127433353857">"Функция недоступна"</item> <item msgid="5044688398303285224">"Откл."</item> diff --git a/packages/SystemUI/res/values-si/strings.xml b/packages/SystemUI/res/values-si/strings.xml index eb447b9e9708..46b82e37d673 100644 --- a/packages/SystemUI/res/values-si/strings.xml +++ b/packages/SystemUI/res/values-si/strings.xml @@ -388,6 +388,9 @@ <string name="performance" msgid="6552785217174378320">"කාර්ය සාධනය"</string> <string name="user_interface" msgid="3712869377953950887">"පරිශීලක අතුරු මුහුණත"</string> <string name="thermal" msgid="6758074791325414831">"තාප"</string> + <string name="custom" msgid="3337456985275158299">"අභිරුචි"</string> + <string name="custom_trace_settings_dialog_title" msgid="2608570500144830554">"අභිරුචි ලුහුබැඳීම් සැකසීම්"</string> + <string name="restore_default" msgid="5259420807486239755">"පෙරනිමිය ප්රතිසාධනය කරන්න"</string> <string name="quick_settings_onehanded_label" msgid="2416537930246274991">"තනි අත් ප්රකාරය"</string> <string name="quick_settings_hearing_devices_label" msgid="7277170419679404129">"ශ්රවණ උපාංග"</string> <string name="quick_settings_hearing_devices_connected" msgid="6519069502397037781">"ක්රියාකාරී"</string> @@ -429,9 +432,13 @@ <string name="zen_modes_dialog_title" msgid="4159138230418567383">"ප්රමුඛතා ප්රකාර"</string> <string name="zen_modes_dialog_done" msgid="6654130880256438950">"නිමයි"</string> <string name="zen_modes_dialog_settings" msgid="2310248023728936697">"සැකසීම්"</string> - <!-- no translation found for zen_mode_on (9085304934016242591) --> + <string name="zen_mode_on" msgid="9085304934016242591">"ක්රියාත්මකයි"</string> + <string name="zen_mode_off" msgid="1736604456618147306">"ක්රියාවිරහිතයි"</string> + <!-- no translation found for zen_mode_set_up (7457957033034460064) --> <skip /> - <!-- no translation found for zen_mode_off (1736604456618147306) --> + <!-- no translation found for zen_mode_no_manual_invocation (1769975741344633672) --> + <skip /> + <!-- no translation found for zen_mode_active_modes (1625850411578488856) --> <skip /> <string name="zen_priority_introduction" msgid="3159291973383796646">"එලාම සිහිකැඳවීම්, සිදුවීම්, සහ ඔබ සඳහන් කළ අමතන්නන් හැර, ශබ්ද සහ කම්පනවලින් ඔබට බාධා නොවනු ඇත. සංගීතය, වීඩියෝ, සහ ක්රීඩා ඇතුළු ඔබ වාදනය කිරීමට තෝරන ලද සියලු දේ ඔබට තවම ඇසෙනු ඇත."</string> <string name="zen_alarms_introduction" msgid="3987266042682300470">"එලාම හැර, ශබ්ද සහ කම්පනවලින් ඔබට බාධා නොවනු ඇත. සංගීතය, වීඩියෝ, සහ ක්රීඩා ඇතුළු ඔබ වාදනය කිරීමට තෝරන ලද සියලු දේ ඔබට තවම ඇසෙනු ඇත."</string> @@ -471,6 +478,8 @@ <string name="keyguard_indication_charging_time_slowly" msgid="301936949731705417">"<xliff:g id="PERCENTAGE">%2$s</xliff:g> • සෙමින් ආරෝපණය වෙමින් • <xliff:g id="CHARGING_TIME_LEFT">%1$s</xliff:g>කින් සම්පූර්ණ වේ"</string> <string name="keyguard_indication_charging_time_dock" msgid="3149328898931741271">"<xliff:g id="PERCENTAGE">%2$s</xliff:g> • ආරෝපණය වෙමින් • <xliff:g id="CHARGING_TIME_LEFT">%1$s</xliff:g>කින් සම්පූර්ණ වේ"</string> <string name="accessibility_action_open_communal_hub" msgid="3081702792413787849">"අගුළු තිරයෙහි විජට්"</string> + <!-- no translation found for accessibility_announcement_communal_widget_added (6911593106099328271) --> + <skip /> <string name="communal_tutorial_indicator_text" msgid="4503010353591430123">"පොදු නිබන්ධනය ආරම්භ කිරීමට වමට ස්වයිප් කරන්න"</string> <string name="cta_tile_button_to_open_widget_editor" msgid="3871562362382963878">"අභිරුචිකරණය කරන්න"</string> <string name="cta_tile_button_to_dismiss" msgid="3377597875997861754">"අස් කරන්න"</string> @@ -499,8 +508,7 @@ <string name="accessibility_action_label_place_widget" msgid="1914197458644168978">"තෝරන ලද විජට්ටුව තබන්න"</string> <string name="communal_widget_picker_title" msgid="1953369090475731663">"අගුළු තිර විජට්"</string> <string name="communal_widget_picker_description" msgid="490515450110487871">"ඔබේ ටැබ්ලටය අගුළු දමා තිබුණත්, ඕනෑම කෙනෙකුට ඔබේ අගුළු තිරයෙහි විජට් බැලිය හැක."</string> - <!-- no translation found for accessibility_action_label_unselect_widget (1041811747619468698) --> - <skip /> + <string name="accessibility_action_label_unselect_widget" msgid="1041811747619468698">"විජට් නොතෝරන්න"</string> <string name="communal_widgets_disclaimer_title" msgid="1150954395585308868">"අගුළු තිර විජට්"</string> <string name="communal_widgets_disclaimer_text" msgid="1423545475160506349">"විජට් එකක් භාවිතයෙන් යෙදුමක් විවෘත කිරීමට, ඔබට ඒ ඔබ බව සත්යාපනය කිරීමට අවශ්ය වනු ඇත. එසේම, ඔබේ ටැබ්ලටය අගුළු දමා ඇති විට පවා ඕනෑම කෙනෙකුට ඒවා බැලිය හැකි බව මතක තබා ගන්න. සමහර විජට් ඔබේ අගුළු තිරය සඳහා අදහස් කර නොතිබිය හැකි අතර මෙහි එක් කිරීමට අනාරක්ෂිත විය හැක."</string> <string name="communal_widgets_disclaimer_button" msgid="4423059765740780753">"තේරුණා"</string> @@ -557,10 +565,8 @@ <string name="media_projection_action_text" msgid="3634906766918186440">"දැන් අරඹන්න"</string> <string name="empty_shade_text" msgid="8935967157319717412">"දැනුම්දීම් නැත"</string> <string name="no_unseen_notif_text" msgid="395512586119868682">"නව දැනුම්දීම් නැත"</string> - <!-- no translation found for adaptive_notification_edu_hun_title (7790738150177329960) --> - <skip /> - <!-- no translation found for adaptive_notification_edu_hun_text (7743367744129536610) --> - <skip /> + <string name="adaptive_notification_edu_hun_title" msgid="7790738150177329960">"දැනුම්දීම් සිසිල් කිරීම ක්රියාත්මකයි"</string> + <string name="adaptive_notification_edu_hun_text" msgid="7743367744129536610">"ඔබට එකවර දැනුම්දීම් වැඩි ප්රමාණයක් ලැබෙන විට ඔබේ උපාංග පරිමාව සහ ඇඟවීම් මිනිත්තු 2ක් දක්වා ස්වයංක්රීයව අඩු වේ."</string> <string name="go_to_adaptive_notification_settings" msgid="2423690125178298479">"ක්රියාවිරහිත කරන්න"</string> <string name="unlock_to_see_notif_text" msgid="7439033907167561227">"පැරණි දැනුම්දීම් බැලීමට අගුළු හරින්න"</string> <string name="quick_settings_disclosure_parental_controls" msgid="2114102871438223600">"මෙම උපාංගය ඔබගේ මාපියන්ගෙන් අයකු විසින් කළමනාකරණය කෙරේ"</string> @@ -1226,7 +1232,6 @@ <string name="accessibility_fingerprint_bouncer" msgid="7189102492498735519">"සත්යාපනය අවශ්යයි. සත්යාපනය කිරීමට ඇඟිලි සලකුණු සංවේදකය ස්පර්ශ කරන්න."</string> <string name="ongoing_phone_call_content_description" msgid="5332334388483099947">"ක්රියාත්මක වන දුරකථන ඇමතුම"</string> <string name="mobile_data_settings_title" msgid="3955246641380064901">"ජංගම දත්ත"</string> - <string name="preference_summary_default_combination" msgid="8453246369903749670">"<xliff:g id="STATE">%1$s</xliff:g> / <xliff:g id="NETWORKMODE">%2$s</xliff:g>"</string> <string name="mobile_data_connection_active" msgid="944490013299018227">"සම්බන්ධයි"</string> <string name="mobile_data_temp_connection_active" msgid="4590222725908806824">"තාවකාලිකව සම්බන්ධ කළා"</string> <string name="mobile_data_poor_connection" msgid="819617772268371434">"දුර්වල සම්බන්ධතාව"</string> @@ -1380,7 +1385,10 @@ <string name="touchpad_tutorial_done_button" msgid="176168488821755503">"නිමයි"</string> <string name="touchpad_tutorial_gesture_done" msgid="4784438360736821255">"අනර්ඝ වැඩක්!"</string> <string name="touchpad_back_gesture_action_title" msgid="7199067250654332735">"ආපස්සට යන්න"</string> - <string name="touchpad_back_gesture_guidance" msgid="4222430588599527272">"ආපසු යාමට, ස්පර්ශ පුවරුවේ ඕනෑම තැනක ඇඟිලි තුනක් භාවිතයෙන් වමට හෝ දකුණට ස්වයිප් කරන්න."</string> + <!-- no translation found for touchpad_back_gesture_guidance (6263750214998421587) --> + <skip /> + <!-- no translation found for touchpad_back_gesture_finished (5353616006999726249) --> + <skip /> <string name="touchpad_back_gesture_animation_content_description" msgid="2646107450922379918">"ඇඟිලි තුනක් දකුණට සහ වමට චලනය වන බව පෙන්වන ස්පර්ශක පුවරුව"</string> <string name="touchpad_back_gesture_screen_animation_content_description" msgid="4036267494237748710">"පසුපස අභිනය සඳහා සජීවිකරණය පෙන්වන උපාංග තිරය"</string> <string name="keyboard_backlight_dialog_title" msgid="8273102932345564724">"යතුරු පුවරු පසු ආලෝකය"</string> @@ -1388,28 +1396,16 @@ <string name="home_controls_dream_label" msgid="6567105701292324257">"නිවෙස් පාලන"</string> <string name="home_controls_dream_description" msgid="4644150952104035789">"තිර සුරැකුමක් ලෙස ඔබේ නිවසේ පාලන වෙත ඉක්මනින් ප්රවේශ වන්න"</string> <string name="volume_undo_action" msgid="5815519725211877114">"පසුගමනය කරන්න"</string> - <!-- no translation found for back_edu_toast_content (4530314597378982956) --> - <skip /> - <!-- no translation found for home_edu_toast_content (3381071147871955415) --> - <skip /> - <!-- no translation found for overview_edu_toast_content (5797030644017804518) --> - <skip /> - <!-- no translation found for all_apps_edu_toast_content (8807496014667211562) --> - <skip /> - <!-- no translation found for back_edu_notification_title (5624780717751357278) --> - <skip /> - <!-- no translation found for back_edu_notification_content (2497557451540954068) --> - <skip /> - <!-- no translation found for home_edu_notification_title (6097902076909654045) --> - <skip /> - <!-- no translation found for home_edu_notification_content (6631697734535766588) --> - <skip /> - <!-- no translation found for overview_edu_notification_title (1265824157319562406) --> - <skip /> - <!-- no translation found for overview_edu_notification_content (3578204677648432500) --> - <skip /> - <!-- no translation found for all_apps_edu_notification_title (372262997265569063) --> - <skip /> - <!-- no translation found for all_apps_edu_notification_content (3255070575694025585) --> - <skip /> + <string name="back_edu_toast_content" msgid="4530314597378982956">"ආපසු යාමට, ස්පර්ශ පුවරුව මත ඇඟිලි තුනකින් වමට හෝ දකුණට ස්වයිප් කරන්න"</string> + <string name="home_edu_toast_content" msgid="3381071147871955415">"මුල් පිටුවට යාමට, ස්පර්ශ පුවරුව මත ඇඟිලි තුනකින් ඉහළට ස්වයිප් කරන්න"</string> + <string name="overview_edu_toast_content" msgid="5797030644017804518">"මෑත යෙදුම් බැලීමට, ඉහළට ස්වයිප් කර ස්පර්ශ පුවරුව මත ඇඟිලි තුනකින් අල්ලාගෙන සිටින්න"</string> + <string name="all_apps_edu_toast_content" msgid="8807496014667211562">"ඔබේ සියලුම යෙදුම් බැලීමට, ඔබේ යතුරුපුවරුවේ ක්රියාකාරී යතුර ඔබන්න"</string> + <string name="back_edu_notification_title" msgid="5624780717751357278">"ආපසු යාමට ඔබේ ස්පර්ශ පුවරුව භාවිත කරන්න"</string> + <string name="back_edu_notification_content" msgid="2497557451540954068">"ඇඟිලි තුනක් භාවිතයෙන් වමට හෝ දකුණට ස්වයිප් කරන්න. තව ඉංගිත දැන ගැනීමට තට්ටු කරන්න."</string> + <string name="home_edu_notification_title" msgid="6097902076909654045">"මුල් පිටුවට යාමට ඔබේ ස්පර්ශ පුවරුව භාවිත කරන්න"</string> + <string name="home_edu_notification_content" msgid="6631697734535766588">"ඇඟිලි තුනක් භාවිතයෙන් ඉහළට ස්වයිප් කරන්න. තව ඉංගිත දැන ගැනීමට තට්ටු කරන්න."</string> + <string name="overview_edu_notification_title" msgid="1265824157319562406">"මෑත යෙදුම් බැලීමට ඔබේ ස්පර්ශ පුවරුව භාවිත කරන්න"</string> + <string name="overview_edu_notification_content" msgid="3578204677648432500">"ඇඟිලි තුනක් භාවිතයෙන් ඉහළට ස්වයිප් කර අල්ලාගෙන සිටින්න. තව ඉංගිත දැන ගැනීමට තට්ටු කරන්න."</string> + <string name="all_apps_edu_notification_title" msgid="372262997265569063">"සියලුම යෙදුම් බැලීමට ඔබේ යතුරු පුවරුව භාවිත කරන්න"</string> + <string name="all_apps_edu_notification_content" msgid="3255070575694025585">"ඕනෑම අවස්ථාවක ක්රියාකාරී යතුර ඔබන්න. තව ඉංගිත දැන ගැනීමට තට්ටු කරන්න."</string> </resources> diff --git a/packages/SystemUI/res/values-si/tiles_states_strings.xml b/packages/SystemUI/res/values-si/tiles_states_strings.xml index 4bebcc05d481..681f3d52bc09 100644 --- a/packages/SystemUI/res/values-si/tiles_states_strings.xml +++ b/packages/SystemUI/res/values-si/tiles_states_strings.xml @@ -56,11 +56,6 @@ <item msgid="5376619709702103243">"අක්රියයි"</item> <item msgid="4875147066469902392">"සක්රියයි"</item> </string-array> - <string-array name="tile_states_modes"> - <item msgid="7764936419245199023">"නොමැත"</item> - <item msgid="2004750556637773692">"ක්රියාවිරහිතයි"</item> - <item msgid="8968530753931637871">"ක්රියාත්මකයි"</item> - </string-array> <string-array name="tile_states_flashlight"> <item msgid="3465257127433353857">"නොමැත"</item> <item msgid="5044688398303285224">"අක්රියයි"</item> diff --git a/packages/SystemUI/res/values-sk/strings.xml b/packages/SystemUI/res/values-sk/strings.xml index 8c2e2a9dc0d0..b6077396378a 100644 --- a/packages/SystemUI/res/values-sk/strings.xml +++ b/packages/SystemUI/res/values-sk/strings.xml @@ -128,13 +128,13 @@ <string name="screenrecord_start_error" msgid="2200660692479682368">"Pri spustení nahrávania obrazovky sa vyskytla chyba"</string> <string name="screenrecord_stop_dialog_title" msgid="8716193661764511095">"Chcete zastaviť nahrávanie?"</string> <string name="screenrecord_stop_dialog_message" msgid="6262768207331626817">"Momentálne nahrávate celú obrazovku"</string> - <string name="screenrecord_stop_dialog_message_specific_app" msgid="5995770227684523244">"Momentálne nahrávate <xliff:g id="APP_NAME">%1$s</xliff:g>"</string> + <string name="screenrecord_stop_dialog_message_specific_app" msgid="5995770227684523244">"Momentálne nahrávate aplikáciu <xliff:g id="APP_NAME">%1$s</xliff:g>"</string> <string name="screenrecord_stop_dialog_button" msgid="2883812564938194350">"Zastaviť nahrávanie"</string> <string name="share_to_app_chip_accessibility_label" msgid="4210256229976947065">"Zdieľa sa obrazovka"</string> <string name="share_to_app_stop_dialog_title" msgid="9212915050910250438">"Chcete prestať zdieľať obrazovku?"</string> <string name="share_to_app_stop_dialog_message_entire_screen_with_host_app" msgid="522823522115375414">"Momentálne zdieľate celú obrazovku s aplikáciou <xliff:g id="HOST_APP_NAME">%1$s</xliff:g>"</string> <string name="share_to_app_stop_dialog_message_entire_screen" msgid="5090115386271179270">"Momentálne zdieľate celú obrazovku s aplikáciou"</string> - <string name="share_to_app_stop_dialog_message_single_app_specific" msgid="5923772039347985172">"Momentálne zdieľate <xliff:g id="APP_BEING_SHARED_NAME">%1$s</xliff:g>"</string> + <string name="share_to_app_stop_dialog_message_single_app_specific" msgid="5923772039347985172">"Momentálne zdieľate aplikáciu <xliff:g id="APP_BEING_SHARED_NAME">%1$s</xliff:g>"</string> <string name="share_to_app_stop_dialog_message_single_app_generic" msgid="6681016774654578261">"Momentálne zdieľate aplikáciu"</string> <string name="share_to_app_stop_dialog_button" msgid="6334056916284230217">"Prestať zdieľať"</string> <string name="cast_screen_to_other_device_chip_accessibility_label" msgid="4687917476203009885">"Prenáša sa obrazovka"</string> @@ -388,6 +388,9 @@ <string name="performance" msgid="6552785217174378320">"Výkon"</string> <string name="user_interface" msgid="3712869377953950887">"Používateľské rozhranie"</string> <string name="thermal" msgid="6758074791325414831">"Termálne"</string> + <string name="custom" msgid="3337456985275158299">"Vlastné"</string> + <string name="custom_trace_settings_dialog_title" msgid="2608570500144830554">"Nastavenia vlastnej stopy"</string> + <string name="restore_default" msgid="5259420807486239755">"Obnoviť predvolené"</string> <string name="quick_settings_onehanded_label" msgid="2416537930246274991">"Režim jednej ruky"</string> <string name="quick_settings_hearing_devices_label" msgid="7277170419679404129">"Načúvacie zariadenia"</string> <string name="quick_settings_hearing_devices_connected" msgid="6519069502397037781">"Aktívne"</string> @@ -429,9 +432,13 @@ <string name="zen_modes_dialog_title" msgid="4159138230418567383">"Režimy priority"</string> <string name="zen_modes_dialog_done" msgid="6654130880256438950">"Hotovo"</string> <string name="zen_modes_dialog_settings" msgid="2310248023728936697">"Nastavenia"</string> - <!-- no translation found for zen_mode_on (9085304934016242591) --> + <string name="zen_mode_on" msgid="9085304934016242591">"Zapnuté"</string> + <string name="zen_mode_off" msgid="1736604456618147306">"Vypnuté"</string> + <!-- no translation found for zen_mode_set_up (7457957033034460064) --> <skip /> - <!-- no translation found for zen_mode_off (1736604456618147306) --> + <!-- no translation found for zen_mode_no_manual_invocation (1769975741344633672) --> + <skip /> + <!-- no translation found for zen_mode_active_modes (1625850411578488856) --> <skip /> <string name="zen_priority_introduction" msgid="3159291973383796646">"Nebudú vás vyrušovať zvuky ani vibrácie, iba budíky, pripomenutia, udalosti a volajúci, ktorých určíte. Budete naďalej počuť všetko, čo sa rozhodnete prehrať, ako napríklad hudbu, videá a hry."</string> <string name="zen_alarms_introduction" msgid="3987266042682300470">"Nebudú vás vyrušovať zvuky ani vibrácie, iba budíky. Budete naďalej počuť všetko, čo sa rozhodnete prehrať, ako napríklad hudbu, videá a hry."</string> @@ -471,6 +478,8 @@ <string name="keyguard_indication_charging_time_slowly" msgid="301936949731705417">"<xliff:g id="PERCENTAGE">%2$s</xliff:g> • Nabíja sa pomaly • Do úplného nabitia zostáva <xliff:g id="CHARGING_TIME_LEFT">%1$s</xliff:g>"</string> <string name="keyguard_indication_charging_time_dock" msgid="3149328898931741271">"<xliff:g id="PERCENTAGE">%2$s</xliff:g> • Nabíja sa • Do úplného nabitia zostáva <xliff:g id="CHARGING_TIME_LEFT">%1$s</xliff:g>"</string> <string name="accessibility_action_open_communal_hub" msgid="3081702792413787849">"Miniaplikácie na uzamknutej obrazovke"</string> + <!-- no translation found for accessibility_announcement_communal_widget_added (6911593106099328271) --> + <skip /> <string name="communal_tutorial_indicator_text" msgid="4503010353591430123">"Potiahnutím doľava spustite komunitný návod"</string> <string name="cta_tile_button_to_open_widget_editor" msgid="3871562362382963878">"Prispôsobiť"</string> <string name="cta_tile_button_to_dismiss" msgid="3377597875997861754">"Zavrieť"</string> @@ -499,8 +508,7 @@ <string name="accessibility_action_label_place_widget" msgid="1914197458644168978">"prepnúť vybranú miniaplikáciu"</string> <string name="communal_widget_picker_title" msgid="1953369090475731663">"Miniaplikácie na uzamknutej obrazovke"</string> <string name="communal_widget_picker_description" msgid="490515450110487871">"Miniaplikácie na uzamknutej obrazovke uvidia všetci, aj keď je tablet uzamknutý."</string> - <!-- no translation found for accessibility_action_label_unselect_widget (1041811747619468698) --> - <skip /> + <string name="accessibility_action_label_unselect_widget" msgid="1041811747619468698">"zrušiť výber miniaplikácie"</string> <string name="communal_widgets_disclaimer_title" msgid="1150954395585308868">"Miniaplikácie na uzamknutej obrazovke"</string> <string name="communal_widgets_disclaimer_text" msgid="1423545475160506349">"Ak chcete otvoriť aplikáciu pomocou miniaplikácie, budete musieť overiť svoju totožnosť. Pamätajte, že si miniaplikáciu môže pozrieť ktokoľvek, aj keď máte tablet uzamknutý. Niektoré miniaplikácie možno nie sú určené pre uzamknutú obrazovku a ich pridanie tu môže byť nebezpečné."</string> <string name="communal_widgets_disclaimer_button" msgid="4423059765740780753">"Dobre"</string> @@ -557,10 +565,8 @@ <string name="media_projection_action_text" msgid="3634906766918186440">"Spustiť"</string> <string name="empty_shade_text" msgid="8935967157319717412">"Žiadne upozornenia"</string> <string name="no_unseen_notif_text" msgid="395512586119868682">"Žiadne nové upozornenia"</string> - <!-- no translation found for adaptive_notification_edu_hun_title (7790738150177329960) --> - <skip /> - <!-- no translation found for adaptive_notification_edu_hun_text (7743367744129536610) --> - <skip /> + <string name="adaptive_notification_edu_hun_title" msgid="7790738150177329960">"Stlmenie upozornení je zapnuté"</string> + <string name="adaptive_notification_edu_hun_text" msgid="7743367744129536610">"Keď dostanete priveľa upozornení naraz, hlasitosť vášho zariadenia a počet upozornení sa automaticky znížia až na dve minúty."</string> <string name="go_to_adaptive_notification_settings" msgid="2423690125178298479">"Vypnúť"</string> <string name="unlock_to_see_notif_text" msgid="7439033907167561227">"Odomknutím zobrazíte staršie upozornenia"</string> <string name="quick_settings_disclosure_parental_controls" msgid="2114102871438223600">"Toto zariadenie spravuje tvoj rodič"</string> @@ -1226,7 +1232,6 @@ <string name="accessibility_fingerprint_bouncer" msgid="7189102492498735519">"Vyžaduje sa overenie. Dotknite sa senzora odtlačkov prstov."</string> <string name="ongoing_phone_call_content_description" msgid="5332334388483099947">"Prebiehajúci telefonický hovor"</string> <string name="mobile_data_settings_title" msgid="3955246641380064901">"Mobilné dáta"</string> - <string name="preference_summary_default_combination" msgid="8453246369903749670">"<xliff:g id="STATE">%1$s</xliff:g>/<xliff:g id="NETWORKMODE">%2$s</xliff:g>"</string> <string name="mobile_data_connection_active" msgid="944490013299018227">"Pripojené"</string> <string name="mobile_data_temp_connection_active" msgid="4590222725908806824">"Dočasne pripojené"</string> <string name="mobile_data_poor_connection" msgid="819617772268371434">"Slabé pripojenie"</string> @@ -1380,7 +1385,10 @@ <string name="touchpad_tutorial_done_button" msgid="176168488821755503">"Hotovo"</string> <string name="touchpad_tutorial_gesture_done" msgid="4784438360736821255">"Skvelé!"</string> <string name="touchpad_back_gesture_action_title" msgid="7199067250654332735">"Prejsť späť"</string> - <string name="touchpad_back_gesture_guidance" msgid="4222430588599527272">"Ak chcete prejsť späť, potiahnite doľava alebo doprava troma prstami kdekoľvek na touchpade."</string> + <!-- no translation found for touchpad_back_gesture_guidance (6263750214998421587) --> + <skip /> + <!-- no translation found for touchpad_back_gesture_finished (5353616006999726249) --> + <skip /> <string name="touchpad_back_gesture_animation_content_description" msgid="2646107450922379918">"Tri prsty na touchpade pohybujúce sa doprava a doľava"</string> <string name="touchpad_back_gesture_screen_animation_content_description" msgid="4036267494237748710">"Obrazovka zariadenia, na ktorej je animácia gesta späť"</string> <string name="keyboard_backlight_dialog_title" msgid="8273102932345564724">"Podsvietenie klávesnice"</string> @@ -1388,28 +1396,16 @@ <string name="home_controls_dream_label" msgid="6567105701292324257">"Ovládanie domácnosti"</string> <string name="home_controls_dream_description" msgid="4644150952104035789">"Rýchly prístup k ovládaniu domácnosti z šetriča obrazovky"</string> <string name="volume_undo_action" msgid="5815519725211877114">"Vrátiť späť"</string> - <!-- no translation found for back_edu_toast_content (4530314597378982956) --> - <skip /> - <!-- no translation found for home_edu_toast_content (3381071147871955415) --> - <skip /> - <!-- no translation found for overview_edu_toast_content (5797030644017804518) --> - <skip /> - <!-- no translation found for all_apps_edu_toast_content (8807496014667211562) --> - <skip /> - <!-- no translation found for back_edu_notification_title (5624780717751357278) --> - <skip /> - <!-- no translation found for back_edu_notification_content (2497557451540954068) --> - <skip /> - <!-- no translation found for home_edu_notification_title (6097902076909654045) --> - <skip /> - <!-- no translation found for home_edu_notification_content (6631697734535766588) --> - <skip /> - <!-- no translation found for overview_edu_notification_title (1265824157319562406) --> - <skip /> - <!-- no translation found for overview_edu_notification_content (3578204677648432500) --> - <skip /> - <!-- no translation found for all_apps_edu_notification_title (372262997265569063) --> - <skip /> - <!-- no translation found for all_apps_edu_notification_content (3255070575694025585) --> - <skip /> + <string name="back_edu_toast_content" msgid="4530314597378982956">"Ak chcete prejsť späť, potiahnite po touchpade troma prstami doľava alebo doprava"</string> + <string name="home_edu_toast_content" msgid="3381071147871955415">"Ak sa chcete vrátiť na plochu, potiahnite po touchpade troma prstami nahor."</string> + <string name="overview_edu_toast_content" msgid="5797030644017804518">"Ak si chcete zobraziť nedávne aplikácie, potiahnite po touchpade troma prstami nahor a pridržte ich."</string> + <string name="all_apps_edu_toast_content" msgid="8807496014667211562">"Ak si chcete zobraziť všetky aplikácie, stlačte na klávesnici akčný kláves"</string> + <string name="back_edu_notification_title" msgid="5624780717751357278">"Prechádzajte späť pomocou touchpadu"</string> + <string name="back_edu_notification_content" msgid="2497557451540954068">"Potiahnite troma prstami doľava alebo doprava. Viac o gestách sa dozviete klepnutím."</string> + <string name="home_edu_notification_title" msgid="6097902076909654045">"Vráťte sa na plochu pomocou touchpadu"</string> + <string name="home_edu_notification_content" msgid="6631697734535766588">"Potiahnite troma prstami nahor. Viac o gestách sa dozviete klepnutím."</string> + <string name="overview_edu_notification_title" msgid="1265824157319562406">"Zobrazte si nedávne aplikácie pomocou touchpadu"</string> + <string name="overview_edu_notification_content" msgid="3578204677648432500">"Potiahnite troma prstami nahor a pridržte ich. Viac o gestách sa dozviete klepnutím."</string> + <string name="all_apps_edu_notification_title" msgid="372262997265569063">"Zobrazte si všetky aplikácie pomocou klávesnice"</string> + <string name="all_apps_edu_notification_content" msgid="3255070575694025585">"Akčný kláves môžete stlačiť kedykoľvek. Viac o gestách sa dozviete klepnutím."</string> </resources> diff --git a/packages/SystemUI/res/values-sk/tiles_states_strings.xml b/packages/SystemUI/res/values-sk/tiles_states_strings.xml index b0fed02848f8..6b5af805f15b 100644 --- a/packages/SystemUI/res/values-sk/tiles_states_strings.xml +++ b/packages/SystemUI/res/values-sk/tiles_states_strings.xml @@ -56,11 +56,6 @@ <item msgid="5376619709702103243">"Vypnuté"</item> <item msgid="4875147066469902392">"Zapnuté"</item> </string-array> - <string-array name="tile_states_modes"> - <item msgid="7764936419245199023">"Nedostupné"</item> - <item msgid="2004750556637773692">"Vypnuté"</item> - <item msgid="8968530753931637871">"Zapnuté"</item> - </string-array> <string-array name="tile_states_flashlight"> <item msgid="3465257127433353857">"Nie je k dispozícii"</item> <item msgid="5044688398303285224">"Vypnuté"</item> diff --git a/packages/SystemUI/res/values-sl/strings.xml b/packages/SystemUI/res/values-sl/strings.xml index 68117afb1328..69f63b99202c 100644 --- a/packages/SystemUI/res/values-sl/strings.xml +++ b/packages/SystemUI/res/values-sl/strings.xml @@ -218,7 +218,7 @@ <string name="biometric_re_enroll_notification_content" msgid="8685925877186288180">"To je potrebno, če želite izboljšati varnost in učinkovitost delovanja."</string> <string name="fingerprint_re_enroll_notification_title" msgid="4539432429683916604">"Vnovična nastavitev odklepanja s prstnim odtisom"</string> <string name="fingerprint_re_enroll_notification_name" msgid="630798657797645704">"Odklepanje s prstnim odtisom"</string> - <string name="fingerprint_re_enroll_dialog_title" msgid="3526033128113925780">"Nastavitev odklepanja s prstnim odtisom"</string> + <string name="fingerprint_re_enroll_dialog_title" msgid="3526033128113925780">"Nastavite odklepanje s prstnim odtisom"</string> <string name="fingerprint_re_enroll_dialog_content" msgid="4866561176695984879">"Če želite znova nastaviti odklepanje s prstnim odtisom, bodo trenutne slike in modeli prstnih odtisov izbrisani.\n\nPo izbrisu boste morali znova nastaviti odklepanje s prstnim odtisom, da boste telefon lahko odklenili s prstnim odtisom ali potrdili svojo identiteto."</string> <string name="fingerprint_re_enroll_dialog_content_singular" msgid="3083663339787381218">"Če želite znova nastaviti odklepanje s prstnim odtisom, bodo trenutne slike in model prstnih odtisov izbrisani.\n\nPo izbrisu boste morali znova nastaviti odklepanje s prstnim odtisom, da boste telefon lahko odklenili s prstnim odtisom ali potrdili svojo identiteto."</string> <string name="fingerprint_reenroll_failure_dialog_content" msgid="4733768492747300666">"Odklepanja s prstnim odtisom ni bilo mogoče nastaviti. Odprite nastavitve in poskusite znova."</string> @@ -388,6 +388,9 @@ <string name="performance" msgid="6552785217174378320">"Učinkovitost delovanja"</string> <string name="user_interface" msgid="3712869377953950887">"Uporabniški vmesnik"</string> <string name="thermal" msgid="6758074791325414831">"Toplotno"</string> + <string name="custom" msgid="3337456985275158299">"Po meri"</string> + <string name="custom_trace_settings_dialog_title" msgid="2608570500144830554">"Nastavitve sledi po meri"</string> + <string name="restore_default" msgid="5259420807486239755">"Obnovi privzeto"</string> <string name="quick_settings_onehanded_label" msgid="2416537930246274991">"Enoročni način"</string> <string name="quick_settings_hearing_devices_label" msgid="7277170419679404129">"Slušni pripomočki"</string> <string name="quick_settings_hearing_devices_connected" msgid="6519069502397037781">"Aktivno"</string> @@ -429,9 +432,13 @@ <string name="zen_modes_dialog_title" msgid="4159138230418567383">"Prednostni načini"</string> <string name="zen_modes_dialog_done" msgid="6654130880256438950">"Končano"</string> <string name="zen_modes_dialog_settings" msgid="2310248023728936697">"Nastavitve"</string> - <!-- no translation found for zen_mode_on (9085304934016242591) --> + <string name="zen_mode_on" msgid="9085304934016242591">"Vklopljeno"</string> + <string name="zen_mode_off" msgid="1736604456618147306">"Izklopljeno"</string> + <!-- no translation found for zen_mode_set_up (7457957033034460064) --> <skip /> - <!-- no translation found for zen_mode_off (1736604456618147306) --> + <!-- no translation found for zen_mode_no_manual_invocation (1769975741344633672) --> + <skip /> + <!-- no translation found for zen_mode_active_modes (1625850411578488856) --> <skip /> <string name="zen_priority_introduction" msgid="3159291973383796646">"Ne bodo vas motili zvoki ali vibriranje, razen v primeru alarmov, opomnikov, dogodkov in klicateljev, ki jih določite. Še vedno pa boste slišali vse, kar se boste odločili predvajati, vključno z glasbo, videoposnetki in igrami."</string> <string name="zen_alarms_introduction" msgid="3987266042682300470">"Ne bodo vas motili zvoki ali vibriranje, razen v primeru alarmov. Še vedno pa boste slišali vse, kar se boste odločili predvajati, vključno z glasbo, videoposnetki in igrami."</string> @@ -471,6 +478,8 @@ <string name="keyguard_indication_charging_time_slowly" msgid="301936949731705417">"<xliff:g id="PERCENTAGE">%2$s</xliff:g> • Počasno polnjenje • Napolnjeno čez <xliff:g id="CHARGING_TIME_LEFT">%1$s</xliff:g>"</string> <string name="keyguard_indication_charging_time_dock" msgid="3149328898931741271">"<xliff:g id="PERCENTAGE">%2$s</xliff:g> • Polnjenje • Napolnjeno čez <xliff:g id="CHARGING_TIME_LEFT">%1$s</xliff:g>"</string> <string name="accessibility_action_open_communal_hub" msgid="3081702792413787849">"Pripomočki na zaklenjenem zaslonu"</string> + <!-- no translation found for accessibility_announcement_communal_widget_added (6911593106099328271) --> + <skip /> <string name="communal_tutorial_indicator_text" msgid="4503010353591430123">"Povlecite levo, da zaženete vadnico za skupnost"</string> <string name="cta_tile_button_to_open_widget_editor" msgid="3871562362382963878">"Prilagodi"</string> <string name="cta_tile_button_to_dismiss" msgid="3377597875997861754">"Opusti"</string> @@ -499,8 +508,7 @@ <string name="accessibility_action_label_place_widget" msgid="1914197458644168978">"postavitev izbranega pripomočka"</string> <string name="communal_widget_picker_title" msgid="1953369090475731663">"Pripomočki na zaklenjenem zaslonu"</string> <string name="communal_widget_picker_description" msgid="490515450110487871">"Pripomočki na zaklenjenem zaslonu so vidni vsem, tudi če je tablica zaklenjena."</string> - <!-- no translation found for accessibility_action_label_unselect_widget (1041811747619468698) --> - <skip /> + <string name="accessibility_action_label_unselect_widget" msgid="1041811747619468698">"preklic izbire pripomočka"</string> <string name="communal_widgets_disclaimer_title" msgid="1150954395585308868">"Pripomočki na zaklenjenem zaslonu"</string> <string name="communal_widgets_disclaimer_text" msgid="1423545475160506349">"Če želite aplikacijo odpreti s pripomočkom, morate potrditi, da ste to vi. Upoštevajte tudi, da si jih lahko ogledajo vsi, tudi ko je tablični računalnik zaklenjen. Nekateri pripomočki morda niso predvideni za uporabo na zaklenjenem zaslonu, zato jih tukaj morda ni varno dodati."</string> <string name="communal_widgets_disclaimer_button" msgid="4423059765740780753">"Razumem"</string> @@ -557,10 +565,8 @@ <string name="media_projection_action_text" msgid="3634906766918186440">"Začni zdaj"</string> <string name="empty_shade_text" msgid="8935967157319717412">"Ni obvestil"</string> <string name="no_unseen_notif_text" msgid="395512586119868682">"Ni novih obvestil"</string> - <!-- no translation found for adaptive_notification_edu_hun_title (7790738150177329960) --> - <skip /> - <!-- no translation found for adaptive_notification_edu_hun_text (7743367744129536610) --> - <skip /> + <string name="adaptive_notification_edu_hun_title" msgid="7790738150177329960">"Utišanje obvestil je vklopljeno"</string> + <string name="adaptive_notification_edu_hun_text" msgid="7743367744129536610">"Ko prejmete preveč obvestil naenkrat, se glasnost naprave in opozoril samodejno zmanjša za največ 2 minuti."</string> <string name="go_to_adaptive_notification_settings" msgid="2423690125178298479">"Izklopi"</string> <string name="unlock_to_see_notif_text" msgid="7439033907167561227">"Odklenite za ogled starejših obvestil"</string> <string name="quick_settings_disclosure_parental_controls" msgid="2114102871438223600">"To napravo upravlja tvoj starš"</string> @@ -1226,7 +1232,6 @@ <string name="accessibility_fingerprint_bouncer" msgid="7189102492498735519">"Zahtevano je preverjanje pristnosti. Za preverjanje pristnosti se dotaknite tipala prstnih odtisov."</string> <string name="ongoing_phone_call_content_description" msgid="5332334388483099947">"Poteka klic"</string> <string name="mobile_data_settings_title" msgid="3955246641380064901">"Prenos podatkov v mobilnem omrežju"</string> - <string name="preference_summary_default_combination" msgid="8453246369903749670">"<xliff:g id="STATE">%1$s</xliff:g>/<xliff:g id="NETWORKMODE">%2$s</xliff:g>"</string> <string name="mobile_data_connection_active" msgid="944490013299018227">"Povezano"</string> <string name="mobile_data_temp_connection_active" msgid="4590222725908806824">"Začasno vzpostavljena povezava"</string> <string name="mobile_data_poor_connection" msgid="819617772268371434">"Slaba povezava"</string> @@ -1380,7 +1385,10 @@ <string name="touchpad_tutorial_done_button" msgid="176168488821755503">"Končano"</string> <string name="touchpad_tutorial_gesture_done" msgid="4784438360736821255">"Odlično!"</string> <string name="touchpad_back_gesture_action_title" msgid="7199067250654332735">"Nazaj"</string> - <string name="touchpad_back_gesture_guidance" msgid="4222430588599527272">"Za pomik nazaj povlecite levo ali desno s tremi prsti kjer koli na sledilni ploščici."</string> + <!-- no translation found for touchpad_back_gesture_guidance (6263750214998421587) --> + <skip /> + <!-- no translation found for touchpad_back_gesture_finished (5353616006999726249) --> + <skip /> <string name="touchpad_back_gesture_animation_content_description" msgid="2646107450922379918">"Sledilna ploščica s tremi prsti, ki se premikajo desno in levo"</string> <string name="touchpad_back_gesture_screen_animation_content_description" msgid="4036267494237748710">"Zaslon naprave z animacijo, ki prikazuje potezo za pomik nazaj"</string> <string name="keyboard_backlight_dialog_title" msgid="8273102932345564724">"Osvetlitev tipkovnice"</string> @@ -1388,28 +1396,16 @@ <string name="home_controls_dream_label" msgid="6567105701292324257">"Kontrolniki za dom"</string> <string name="home_controls_dream_description" msgid="4644150952104035789">"Hiter dostop do kontrolnikov za dom na ohranjevalniku zaslona"</string> <string name="volume_undo_action" msgid="5815519725211877114">"Razveljavi"</string> - <!-- no translation found for back_edu_toast_content (4530314597378982956) --> - <skip /> - <!-- no translation found for home_edu_toast_content (3381071147871955415) --> - <skip /> - <!-- no translation found for overview_edu_toast_content (5797030644017804518) --> - <skip /> - <!-- no translation found for all_apps_edu_toast_content (8807496014667211562) --> - <skip /> - <!-- no translation found for back_edu_notification_title (5624780717751357278) --> - <skip /> - <!-- no translation found for back_edu_notification_content (2497557451540954068) --> - <skip /> - <!-- no translation found for home_edu_notification_title (6097902076909654045) --> - <skip /> - <!-- no translation found for home_edu_notification_content (6631697734535766588) --> - <skip /> - <!-- no translation found for overview_edu_notification_title (1265824157319562406) --> - <skip /> - <!-- no translation found for overview_edu_notification_content (3578204677648432500) --> - <skip /> - <!-- no translation found for all_apps_edu_notification_title (372262997265569063) --> - <skip /> - <!-- no translation found for all_apps_edu_notification_content (3255070575694025585) --> - <skip /> + <string name="back_edu_toast_content" msgid="4530314597378982956">"Za pomik nazaj povlecite s tremi prsti levo ali desno po sledilni ploščici"</string> + <string name="home_edu_toast_content" msgid="3381071147871955415">"Za pomik na začetni zaslon povlecite s tremi prsti navzgor po sledilni ploščici"</string> + <string name="overview_edu_toast_content" msgid="5797030644017804518">"Za ogled nedavnih aplikacij povlecite s tremi prsti navzgor po sledilni ploščici in pridržite"</string> + <string name="all_apps_edu_toast_content" msgid="8807496014667211562">"Za ogled vseh aplikacij pritisnite tipko za dejanja na tipkovnici"</string> + <string name="back_edu_notification_title" msgid="5624780717751357278">"Uporaba sledilne ploščice za pomik nazaj"</string> + <string name="back_edu_notification_content" msgid="2497557451540954068">"S tremi prsti povlecite levo ali desno. Dotaknite se, če želite spoznati več potez."</string> + <string name="home_edu_notification_title" msgid="6097902076909654045">"Uporaba sledilne ploščice za pomik na začetni zaslon"</string> + <string name="home_edu_notification_content" msgid="6631697734535766588">"S tremi prsti povlecite navzgor. Dotaknite se, če želite spoznati več potez."</string> + <string name="overview_edu_notification_title" msgid="1265824157319562406">"Uporaba sledilne ploščice za ogled nedavnih aplikacij"</string> + <string name="overview_edu_notification_content" msgid="3578204677648432500">"S tremi prsti povlecite navzgor in pridržite. Dotaknite se, če želite spoznati več potez."</string> + <string name="all_apps_edu_notification_title" msgid="372262997265569063">"Uporaba tipkovnice za prikaz vseh aplikacij"</string> + <string name="all_apps_edu_notification_content" msgid="3255070575694025585">"Kadar koli pritisnite tipko za dejanja. Dotaknite se, če želite spoznati več potez."</string> </resources> diff --git a/packages/SystemUI/res/values-sl/tiles_states_strings.xml b/packages/SystemUI/res/values-sl/tiles_states_strings.xml index e57b87b794b3..5f60ffdaebf7 100644 --- a/packages/SystemUI/res/values-sl/tiles_states_strings.xml +++ b/packages/SystemUI/res/values-sl/tiles_states_strings.xml @@ -56,11 +56,6 @@ <item msgid="5376619709702103243">"Izklopljeno"</item> <item msgid="4875147066469902392">"Vklopljeno"</item> </string-array> - <string-array name="tile_states_modes"> - <item msgid="7764936419245199023">"Ni na voljo"</item> - <item msgid="2004750556637773692">"Izklopljeno"</item> - <item msgid="8968530753931637871">"Vklopljeno"</item> - </string-array> <string-array name="tile_states_flashlight"> <item msgid="3465257127433353857">"Ni na voljo"</item> <item msgid="5044688398303285224">"Izklopljeno"</item> diff --git a/packages/SystemUI/res/values-sq/strings.xml b/packages/SystemUI/res/values-sq/strings.xml index debd441e5533..b26c7d8b92ce 100644 --- a/packages/SystemUI/res/values-sq/strings.xml +++ b/packages/SystemUI/res/values-sq/strings.xml @@ -388,6 +388,9 @@ <string name="performance" msgid="6552785217174378320">"Performanca"</string> <string name="user_interface" msgid="3712869377953950887">"Ndërfaqja e përdoruesit"</string> <string name="thermal" msgid="6758074791325414831">"Termike"</string> + <string name="custom" msgid="3337456985275158299">"I personalizuar"</string> + <string name="custom_trace_settings_dialog_title" msgid="2608570500144830554">"Cilësimet e gjurmimit të personalizuar"</string> + <string name="restore_default" msgid="5259420807486239755">"Restauro parazgjedhjen"</string> <string name="quick_settings_onehanded_label" msgid="2416537930246274991">"Modaliteti i përdorimit me një dorë"</string> <string name="quick_settings_hearing_devices_label" msgid="7277170419679404129">"Pajisje ndihmëse për dëgjimin"</string> <string name="quick_settings_hearing_devices_connected" msgid="6519069502397037781">"Aktive"</string> @@ -429,9 +432,13 @@ <string name="zen_modes_dialog_title" msgid="4159138230418567383">"Modalitetet e përparësisë"</string> <string name="zen_modes_dialog_done" msgid="6654130880256438950">"U krye"</string> <string name="zen_modes_dialog_settings" msgid="2310248023728936697">"Cilësimet"</string> - <!-- no translation found for zen_mode_on (9085304934016242591) --> + <string name="zen_mode_on" msgid="9085304934016242591">"Aktiv"</string> + <string name="zen_mode_off" msgid="1736604456618147306">"Joaktiv"</string> + <!-- no translation found for zen_mode_set_up (7457957033034460064) --> <skip /> - <!-- no translation found for zen_mode_off (1736604456618147306) --> + <!-- no translation found for zen_mode_no_manual_invocation (1769975741344633672) --> + <skip /> + <!-- no translation found for zen_mode_active_modes (1625850411578488856) --> <skip /> <string name="zen_priority_introduction" msgid="3159291973383796646">"Nuk do të shqetësohesh nga tingujt dhe dridhjet, përveç alarmeve, alarmeve rikujtuese, ngjarjeve dhe telefonuesve që specifikon. Do të vazhdosh të dëgjosh çdo gjë që zgjedh të luash duke përfshirë muzikën, videot dhe lojërat."</string> <string name="zen_alarms_introduction" msgid="3987266042682300470">"Nuk do të shqetësohesh nga tingujt dhe dridhjet, përveç alarmeve. Do të vazhdosh të dëgjosh çdo gjë që zgjedh të luash duke përfshirë muzikën, videot dhe lojërat."</string> @@ -471,6 +478,8 @@ <string name="keyguard_indication_charging_time_slowly" msgid="301936949731705417">"<xliff:g id="PERCENTAGE">%2$s</xliff:g> • Po karikohet ngadalë • Plot për <xliff:g id="CHARGING_TIME_LEFT">%1$s</xliff:g>"</string> <string name="keyguard_indication_charging_time_dock" msgid="3149328898931741271">"<xliff:g id="PERCENTAGE">%2$s</xliff:g> • Po karikohet • Plot për <xliff:g id="CHARGING_TIME_LEFT">%1$s</xliff:g>"</string> <string name="accessibility_action_open_communal_hub" msgid="3081702792413787849">"Miniaplikacionet në ekranin e kyçjes"</string> + <!-- no translation found for accessibility_announcement_communal_widget_added (6911593106099328271) --> + <skip /> <string name="communal_tutorial_indicator_text" msgid="4503010353591430123">"Rrëshqit shpejt majtas për të filluar udhëzuesin e përbashkët"</string> <string name="cta_tile_button_to_open_widget_editor" msgid="3871562362382963878">"Personalizo"</string> <string name="cta_tile_button_to_dismiss" msgid="3377597875997861754">"Hiq"</string> @@ -499,8 +508,7 @@ <string name="accessibility_action_label_place_widget" msgid="1914197458644168978">"vendos miniaplikacionin e zgjedhur"</string> <string name="communal_widget_picker_title" msgid="1953369090475731663">"Kyç miniaplikacionet e ekranit"</string> <string name="communal_widget_picker_description" msgid="490515450110487871">"Çdo person mund të shikojë miniaplikacionet në ekranin tënd të kyçjes, edhe nëse tableti është i kyçur."</string> - <!-- no translation found for accessibility_action_label_unselect_widget (1041811747619468698) --> - <skip /> + <string name="accessibility_action_label_unselect_widget" msgid="1041811747619468698">"anulo zgjedhjen e miniaplikacionit"</string> <string name="communal_widgets_disclaimer_title" msgid="1150954395585308868">"Kyç miniaplikacionet e ekranit"</string> <string name="communal_widgets_disclaimer_text" msgid="1423545475160506349">"Për të hapur një aplikacion duke përdorur një miniaplikacion, do të duhet të verifikosh që je ti. Ki parasysh gjithashtu që çdo person mund t\'i shikojë, edhe kur tableti yt është i kyçur. Disa miniaplikacione mund të mos jenë planifikuar për ekranin tënd të kyçjes dhe mund të mos jetë e sigurt t\'i shtosh këtu."</string> <string name="communal_widgets_disclaimer_button" msgid="4423059765740780753">"E kuptova"</string> @@ -557,10 +565,8 @@ <string name="media_projection_action_text" msgid="3634906766918186440">"Fillo tani"</string> <string name="empty_shade_text" msgid="8935967157319717412">"Asnjë njoftim"</string> <string name="no_unseen_notif_text" msgid="395512586119868682">"Nuk ka njoftime të reja"</string> - <!-- no translation found for adaptive_notification_edu_hun_title (7790738150177329960) --> - <skip /> - <!-- no translation found for adaptive_notification_edu_hun_text (7743367744129536610) --> - <skip /> + <string name="adaptive_notification_edu_hun_title" msgid="7790738150177329960">"Reduktimi i njoftimeve është aktiv"</string> + <string name="adaptive_notification_edu_hun_text" msgid="7743367744129536610">"Volumi i pajisjes dhe sinjalizimet zvogëlohen automatikisht për deri në 2 minuta kur merr shumë njoftime në të njëjtën kohë."</string> <string name="go_to_adaptive_notification_settings" msgid="2423690125178298479">"Çaktivizo"</string> <string name="unlock_to_see_notif_text" msgid="7439033907167561227">"Shkyç për të parë njoftimet e vjetra"</string> <string name="quick_settings_disclosure_parental_controls" msgid="2114102871438223600">"Kjo pajisje menaxhohet nga prindi yt"</string> @@ -1226,7 +1232,6 @@ <string name="accessibility_fingerprint_bouncer" msgid="7189102492498735519">"Kërkohet vërtetimi. Prek sensorin e gjurmës së gishtit për t\'u vërtetuar."</string> <string name="ongoing_phone_call_content_description" msgid="5332334388483099947">"Telefonatë në vazhdim"</string> <string name="mobile_data_settings_title" msgid="3955246641380064901">"Të dhënat celulare"</string> - <string name="preference_summary_default_combination" msgid="8453246369903749670">"<xliff:g id="STATE">%1$s</xliff:g>/<xliff:g id="NETWORKMODE">%2$s</xliff:g>"</string> <string name="mobile_data_connection_active" msgid="944490013299018227">"Lidhur"</string> <string name="mobile_data_temp_connection_active" msgid="4590222725908806824">"Lidhur përkohësisht"</string> <string name="mobile_data_poor_connection" msgid="819617772268371434">"Lidhje e dobët"</string> @@ -1380,7 +1385,10 @@ <string name="touchpad_tutorial_done_button" msgid="176168488821755503">"U krye"</string> <string name="touchpad_tutorial_gesture_done" msgid="4784438360736821255">"Punë e shkëlqyer!"</string> <string name="touchpad_back_gesture_action_title" msgid="7199067250654332735">"Kthehu prapa"</string> - <string name="touchpad_back_gesture_guidance" msgid="4222430588599527272">"Për t\'u kthyer prapa, rrëshqit shpejt majtas ose djathtas duke përdorur tre gishta kudo në bllokun me prekje."</string> + <!-- no translation found for touchpad_back_gesture_guidance (6263750214998421587) --> + <skip /> + <!-- no translation found for touchpad_back_gesture_finished (5353616006999726249) --> + <skip /> <string name="touchpad_back_gesture_animation_content_description" msgid="2646107450922379918">"Blloku me prekje që tregon tre gishta që lëvizin djathtas dhe majtas"</string> <string name="touchpad_back_gesture_screen_animation_content_description" msgid="4036267494237748710">"Ekrani i pajisjes që tregon një animacion për gjestin e kthimit prapa"</string> <string name="keyboard_backlight_dialog_title" msgid="8273102932345564724">"Drita e sfondit e tastierës"</string> @@ -1388,28 +1396,16 @@ <string name="home_controls_dream_label" msgid="6567105701292324257">"Kontrollet e shtëpisë"</string> <string name="home_controls_dream_description" msgid="4644150952104035789">"Qasu te kontrollet e shtëpisë si mbrojtës ekrani"</string> <string name="volume_undo_action" msgid="5815519725211877114">"Zhbëj"</string> - <!-- no translation found for back_edu_toast_content (4530314597378982956) --> - <skip /> - <!-- no translation found for home_edu_toast_content (3381071147871955415) --> - <skip /> - <!-- no translation found for overview_edu_toast_content (5797030644017804518) --> - <skip /> - <!-- no translation found for all_apps_edu_toast_content (8807496014667211562) --> - <skip /> - <!-- no translation found for back_edu_notification_title (5624780717751357278) --> - <skip /> - <!-- no translation found for back_edu_notification_content (2497557451540954068) --> - <skip /> - <!-- no translation found for home_edu_notification_title (6097902076909654045) --> - <skip /> - <!-- no translation found for home_edu_notification_content (6631697734535766588) --> - <skip /> - <!-- no translation found for overview_edu_notification_title (1265824157319562406) --> - <skip /> - <!-- no translation found for overview_edu_notification_content (3578204677648432500) --> - <skip /> - <!-- no translation found for all_apps_edu_notification_title (372262997265569063) --> - <skip /> - <!-- no translation found for all_apps_edu_notification_content (3255070575694025585) --> - <skip /> + <string name="back_edu_toast_content" msgid="4530314597378982956">"Për t\'u kthyer prapa, rrëshqit shpejt majtas ose djathtas me tre gishta në bllokun me prekje"</string> + <string name="home_edu_toast_content" msgid="3381071147871955415">"Për të shkuar tek ekrani bazë, rrëshqit shpejt lart me tre gishta në bllokun me prekje"</string> + <string name="overview_edu_toast_content" msgid="5797030644017804518">"Për aplikacionet e fundit, rrëshqit shpejt lart dhe mbaj shtypur me tre gishta në bllokun me prekje"</string> + <string name="all_apps_edu_toast_content" msgid="8807496014667211562">"Për të shikuar të gjitha aplikacionet, shtyp tastin e veprimit në tastierë"</string> + <string name="back_edu_notification_title" msgid="5624780717751357278">"Përdor bllokun me prekje për t\'u kthyer prapa"</string> + <string name="back_edu_notification_content" msgid="2497557451540954068">"Rrëshqit shpejt majtas ose djathtas duke përdorur tre gishta. Trokit për të mësuar më shumë gjeste."</string> + <string name="home_edu_notification_title" msgid="6097902076909654045">"Përdor bllokun me prekje për të shkuar tek ekrani bazë"</string> + <string name="home_edu_notification_content" msgid="6631697734535766588">"Rrëshqit shpejt lart duke përdorur tre gishta. Trokit për të mësuar më shumë gjeste."</string> + <string name="overview_edu_notification_title" msgid="1265824157319562406">"Përdor bllokun me prekje për të shikuar aplikacionet e fundit"</string> + <string name="overview_edu_notification_content" msgid="3578204677648432500">"Rrëshqit shpejt lart dhe mbaj shtypur me tre gishta. Trokit për të mësuar më shumë gjeste."</string> + <string name="all_apps_edu_notification_title" msgid="372262997265569063">"Përdor tastierën për të shikuar të gjitha aplikacionet"</string> + <string name="all_apps_edu_notification_content" msgid="3255070575694025585">"Shtyp tastin e veprimit në çdo kohë. Trokit për të mësuar më shumë gjeste."</string> </resources> diff --git a/packages/SystemUI/res/values-sq/tiles_states_strings.xml b/packages/SystemUI/res/values-sq/tiles_states_strings.xml index 126d0dc28005..9b5032eecbd8 100644 --- a/packages/SystemUI/res/values-sq/tiles_states_strings.xml +++ b/packages/SystemUI/res/values-sq/tiles_states_strings.xml @@ -56,11 +56,6 @@ <item msgid="5376619709702103243">"Joaktiv"</item> <item msgid="4875147066469902392">"Aktiv"</item> </string-array> - <string-array name="tile_states_modes"> - <item msgid="7764936419245199023">"Nuk ofrohet"</item> - <item msgid="2004750556637773692">"Joaktiv"</item> - <item msgid="8968530753931637871">"Aktiv"</item> - </string-array> <string-array name="tile_states_flashlight"> <item msgid="3465257127433353857">"Nuk ofrohet"</item> <item msgid="5044688398303285224">"Joaktiv"</item> diff --git a/packages/SystemUI/res/values-sr/strings.xml b/packages/SystemUI/res/values-sr/strings.xml index 8dccb4409c99..7acfbf5f403e 100644 --- a/packages/SystemUI/res/values-sr/strings.xml +++ b/packages/SystemUI/res/values-sr/strings.xml @@ -141,7 +141,7 @@ <string name="cast_to_other_device_stop_dialog_title" msgid="7836517190930357326">"Желите да зауставите пребацивање?"</string> <string name="cast_to_other_device_stop_dialog_message_entire_screen_with_device" msgid="1474703115926205251">"Тренутно пребацујете цео екран на: <xliff:g id="DEVICE_NAME">%1$s</xliff:g>"</string> <string name="cast_to_other_device_stop_dialog_message_entire_screen" msgid="8419219169553867625">"Тренутно пребацујете цео екран на уређај у близини"</string> - <string name="cast_to_other_device_stop_dialog_message_specific_app_with_device" msgid="2715934698604085519">"<xliff:g id="APP_BEING_SHARED_NAME">%1$s</xliff:g> се тренутно пребацује на: <xliff:g id="DEVICE_NAME">%2$s</xliff:g>"</string> + <string name="cast_to_other_device_stop_dialog_message_specific_app_with_device" msgid="2715934698604085519">"<xliff:g id="APP_BEING_SHARED_NAME">%1$s</xliff:g> тренутно пребацујете на: <xliff:g id="DEVICE_NAME">%2$s</xliff:g>"</string> <string name="cast_to_other_device_stop_dialog_message_specific_app" msgid="8616103075630934513">"<xliff:g id="APP_BEING_SHARED_NAME">%1$s</xliff:g> се тренутно пребацује на уређај у близини"</string> <string name="cast_to_other_device_stop_dialog_message_generic_with_device" msgid="9213582497852420203">"Тренутно пребацујете на: <xliff:g id="DEVICE_NAME">%1$s</xliff:g>"</string> <string name="cast_to_other_device_stop_dialog_message_generic" msgid="4100272100480415076">"Тренутно пребацујете на уређај у близини"</string> @@ -388,6 +388,9 @@ <string name="performance" msgid="6552785217174378320">"Перформансе"</string> <string name="user_interface" msgid="3712869377953950887">"Кориснички интерфејс"</string> <string name="thermal" msgid="6758074791325414831">"Термална камера"</string> + <string name="custom" msgid="3337456985275158299">"Прилагођено"</string> + <string name="custom_trace_settings_dialog_title" msgid="2608570500144830554">"Подешавања прилагођеног праћења"</string> + <string name="restore_default" msgid="5259420807486239755">"Врати подразумевано"</string> <string name="quick_settings_onehanded_label" msgid="2416537930246274991">"Режим једном руком"</string> <string name="quick_settings_hearing_devices_label" msgid="7277170419679404129">"Слушни апарати"</string> <string name="quick_settings_hearing_devices_connected" msgid="6519069502397037781">"Активно"</string> @@ -429,9 +432,13 @@ <string name="zen_modes_dialog_title" msgid="4159138230418567383">"Приоритетни режими"</string> <string name="zen_modes_dialog_done" msgid="6654130880256438950">"Готово"</string> <string name="zen_modes_dialog_settings" msgid="2310248023728936697">"Подешавања"</string> - <!-- no translation found for zen_mode_on (9085304934016242591) --> + <string name="zen_mode_on" msgid="9085304934016242591">"Укључено"</string> + <string name="zen_mode_off" msgid="1736604456618147306">"Искључено"</string> + <!-- no translation found for zen_mode_set_up (7457957033034460064) --> <skip /> - <!-- no translation found for zen_mode_off (1736604456618147306) --> + <!-- no translation found for zen_mode_no_manual_invocation (1769975741344633672) --> + <skip /> + <!-- no translation found for zen_mode_active_modes (1625850411578488856) --> <skip /> <string name="zen_priority_introduction" msgid="3159291973383796646">"Неће вас узнемиравати звукови и вибрације осим за аларме, подсетнике, догађаје и позиваоце које наведете. И даље ћете чути све што одаберете да пустите, укључујући музику, видео снимке и игре."</string> <string name="zen_alarms_introduction" msgid="3987266042682300470">"Неће вас узнемиравати звукови и вибрације осим за аларме. И даље ћете чути све што одаберете да пустите, укључујући музику, видео снимке и игре."</string> @@ -471,6 +478,8 @@ <string name="keyguard_indication_charging_time_slowly" msgid="301936949731705417">"<xliff:g id="PERCENTAGE">%2$s</xliff:g> • Споро се пуни • <xliff:g id="CHARGING_TIME_LEFT">%1$s</xliff:g> до краја пуњења"</string> <string name="keyguard_indication_charging_time_dock" msgid="3149328898931741271">"<xliff:g id="PERCENTAGE">%2$s</xliff:g> • Пуни се • <xliff:g id="CHARGING_TIME_LEFT">%1$s</xliff:g> до краја пуњења"</string> <string name="accessibility_action_open_communal_hub" msgid="3081702792413787849">"Виџети на закључаном екрану"</string> + <!-- no translation found for accessibility_announcement_communal_widget_added (6911593106099328271) --> + <skip /> <string name="communal_tutorial_indicator_text" msgid="4503010353591430123">"Превуците улево да бисте започели заједнички водич"</string> <string name="cta_tile_button_to_open_widget_editor" msgid="3871562362382963878">"Прилагодите"</string> <string name="cta_tile_button_to_dismiss" msgid="3377597875997861754">"Одбаци"</string> @@ -498,9 +507,8 @@ <string name="accessibility_action_label_remove_widget" msgid="3373779447448758070">"уклоните виџет"</string> <string name="accessibility_action_label_place_widget" msgid="1914197458644168978">"поставите изабрани виџет"</string> <string name="communal_widget_picker_title" msgid="1953369090475731663">"Виџети за закључани екран"</string> - <string name="communal_widget_picker_description" msgid="490515450110487871">"Сви могу да виде веџете на закључаном екрану, чак и када је таблет закључан."</string> - <!-- no translation found for accessibility_action_label_unselect_widget (1041811747619468698) --> - <skip /> + <string name="communal_widget_picker_description" msgid="490515450110487871">"Сви могу да виде виџете на закључаном екрану, чак и када је таблет закључан."</string> + <string name="accessibility_action_label_unselect_widget" msgid="1041811747619468698">"поништи избор виџета"</string> <string name="communal_widgets_disclaimer_title" msgid="1150954395585308868">"Виџети за закључани екран"</string> <string name="communal_widgets_disclaimer_text" msgid="1423545475160506349">"Да бисте отворили апликацију која користи виџет, треба да потврдите да сте то ви. Имајте у виду да свако може да га види, чак и када је таблет закључан. Неки виџети можда нису намењени за закључани екран и можда није безбедно да их тамо додате."</string> <string name="communal_widgets_disclaimer_button" msgid="4423059765740780753">"Важи"</string> @@ -557,10 +565,8 @@ <string name="media_projection_action_text" msgid="3634906766918186440">"Започни"</string> <string name="empty_shade_text" msgid="8935967157319717412">"Нема обавештења"</string> <string name="no_unseen_notif_text" msgid="395512586119868682">"Нема нових обавештења"</string> - <!-- no translation found for adaptive_notification_edu_hun_title (7790738150177329960) --> - <skip /> - <!-- no translation found for adaptive_notification_edu_hun_text (7743367744129536610) --> - <skip /> + <string name="adaptive_notification_edu_hun_title" msgid="7790738150177329960">"Утишавање обавештења је укључено"</string> + <string name="adaptive_notification_edu_hun_text" msgid="7743367744129536610">"Звук и број упозорења на уређају се аутоматски смањују на 2 минута када добијете превише обавештења."</string> <string name="go_to_adaptive_notification_settings" msgid="2423690125178298479">"Искључи"</string> <string name="unlock_to_see_notif_text" msgid="7439033907167561227">"Откључајте за старија обавештења"</string> <string name="quick_settings_disclosure_parental_controls" msgid="2114102871438223600">"Овим уређајем управља родитељ"</string> @@ -1226,7 +1232,6 @@ <string name="accessibility_fingerprint_bouncer" msgid="7189102492498735519">"Потребна је потврда идентитета. Додирните сензор за отисак прста да бисте потврдили идентитет."</string> <string name="ongoing_phone_call_content_description" msgid="5332334388483099947">"Актуелни телефонски позив"</string> <string name="mobile_data_settings_title" msgid="3955246641380064901">"Мобилни подаци"</string> - <string name="preference_summary_default_combination" msgid="8453246369903749670">"<xliff:g id="STATE">%1$s</xliff:g>/<xliff:g id="NETWORKMODE">%2$s</xliff:g>"</string> <string name="mobile_data_connection_active" msgid="944490013299018227">"Повезано"</string> <string name="mobile_data_temp_connection_active" msgid="4590222725908806824">"Привремено повезано"</string> <string name="mobile_data_poor_connection" msgid="819617772268371434">"Веза је лоша"</string> @@ -1380,7 +1385,10 @@ <string name="touchpad_tutorial_done_button" msgid="176168488821755503">"Готово"</string> <string name="touchpad_tutorial_gesture_done" msgid="4784438360736821255">"Одлично!"</string> <string name="touchpad_back_gesture_action_title" msgid="7199067250654332735">"Назад"</string> - <string name="touchpad_back_gesture_guidance" msgid="4222430588599527272">"Да бисте се вратили, превуците улево или удесно са три прста било где на тачпеду."</string> + <!-- no translation found for touchpad_back_gesture_guidance (6263750214998421587) --> + <skip /> + <!-- no translation found for touchpad_back_gesture_finished (5353616006999726249) --> + <skip /> <string name="touchpad_back_gesture_animation_content_description" msgid="2646107450922379918">"Тачпед са приказом три прста који се померају удесно и улево"</string> <string name="touchpad_back_gesture_screen_animation_content_description" msgid="4036267494237748710">"Екран уређаја са приказом анимације покрета за назад"</string> <string name="keyboard_backlight_dialog_title" msgid="8273102932345564724">"Позадинско осветљење тастатуре"</string> @@ -1388,28 +1396,16 @@ <string name="home_controls_dream_label" msgid="6567105701292324257">"Контроле за дом"</string> <string name="home_controls_dream_description" msgid="4644150952104035789">"Брз приступ контролама за дом као чувару екрана"</string> <string name="volume_undo_action" msgid="5815519725211877114">"Опозови"</string> - <!-- no translation found for back_edu_toast_content (4530314597378982956) --> - <skip /> - <!-- no translation found for home_edu_toast_content (3381071147871955415) --> - <skip /> - <!-- no translation found for overview_edu_toast_content (5797030644017804518) --> - <skip /> - <!-- no translation found for all_apps_edu_toast_content (8807496014667211562) --> - <skip /> - <!-- no translation found for back_edu_notification_title (5624780717751357278) --> - <skip /> - <!-- no translation found for back_edu_notification_content (2497557451540954068) --> - <skip /> - <!-- no translation found for home_edu_notification_title (6097902076909654045) --> - <skip /> - <!-- no translation found for home_edu_notification_content (6631697734535766588) --> - <skip /> - <!-- no translation found for overview_edu_notification_title (1265824157319562406) --> - <skip /> - <!-- no translation found for overview_edu_notification_content (3578204677648432500) --> - <skip /> - <!-- no translation found for all_apps_edu_notification_title (372262997265569063) --> - <skip /> - <!-- no translation found for all_apps_edu_notification_content (3255070575694025585) --> - <skip /> + <string name="back_edu_toast_content" msgid="4530314597378982956">"Да бисте се вратили, превуците улево или удесно са три прста на тачпеду"</string> + <string name="home_edu_toast_content" msgid="3381071147871955415">"Да бисте отишли на почетни екран, превуците нагоре са три прста на тачпеду"</string> + <string name="overview_edu_toast_content" msgid="5797030644017804518">"Да бисте прегледали недавне апликације, превуците нагоре и задржите са три прста на тачпеду"</string> + <string name="all_apps_edu_toast_content" msgid="8807496014667211562">"Да бисте погледали све апликације, притисните тастер радњи на тастатури"</string> + <string name="back_edu_notification_title" msgid="5624780717751357278">"Користите тачпед да бисте се вратили"</string> + <string name="back_edu_notification_content" msgid="2497557451540954068">"Превуците улево или удесно са три прста. Додирните да бисте видели више покрета."</string> + <string name="home_edu_notification_title" msgid="6097902076909654045">"Користите тачпед да бисте отишли на почетни екран"</string> + <string name="home_edu_notification_content" msgid="6631697734535766588">"Превуците нагоре са три прста. Додирните да бисте видели више покрета."</string> + <string name="overview_edu_notification_title" msgid="1265824157319562406">"Користите тачпед да бисте прегледали недавне апликације"</string> + <string name="overview_edu_notification_content" msgid="3578204677648432500">"Превуците нагоре и задржите са три прста. Додирните да бисте видели више покрета."</string> + <string name="all_apps_edu_notification_title" msgid="372262997265569063">"Користите тастатуру да бисте прегледали све апликације"</string> + <string name="all_apps_edu_notification_content" msgid="3255070575694025585">"Притисните тастер радњи у било ком тренутку. Додирните да бисте видели више покрета."</string> </resources> diff --git a/packages/SystemUI/res/values-sr/tiles_states_strings.xml b/packages/SystemUI/res/values-sr/tiles_states_strings.xml index ab05c21476fb..2acf1d264213 100644 --- a/packages/SystemUI/res/values-sr/tiles_states_strings.xml +++ b/packages/SystemUI/res/values-sr/tiles_states_strings.xml @@ -56,11 +56,6 @@ <item msgid="5376619709702103243">"Искључено"</item> <item msgid="4875147066469902392">"Укључено"</item> </string-array> - <string-array name="tile_states_modes"> - <item msgid="7764936419245199023">"Недоступно"</item> - <item msgid="2004750556637773692">"Искључено"</item> - <item msgid="8968530753931637871">"Укључено"</item> - </string-array> <string-array name="tile_states_flashlight"> <item msgid="3465257127433353857">"Недоступно"</item> <item msgid="5044688398303285224">"Искључено"</item> diff --git a/packages/SystemUI/res/values-sv/strings.xml b/packages/SystemUI/res/values-sv/strings.xml index 3b6536586f46..b632dde15227 100644 --- a/packages/SystemUI/res/values-sv/strings.xml +++ b/packages/SystemUI/res/values-sv/strings.xml @@ -388,6 +388,9 @@ <string name="performance" msgid="6552785217174378320">"Prestanda"</string> <string name="user_interface" msgid="3712869377953950887">"Användargränssnitt"</string> <string name="thermal" msgid="6758074791325414831">"Termisk"</string> + <string name="custom" msgid="3337456985275158299">"Anpassat"</string> + <string name="custom_trace_settings_dialog_title" msgid="2608570500144830554">"Anpassade spårningsinställningar"</string> + <string name="restore_default" msgid="5259420807486239755">"Återställ standardinställning"</string> <string name="quick_settings_onehanded_label" msgid="2416537930246274991">"Enhandsläge"</string> <string name="quick_settings_hearing_devices_label" msgid="7277170419679404129">"Hörhjälpmedel"</string> <string name="quick_settings_hearing_devices_connected" msgid="6519069502397037781">"Aktiva"</string> @@ -429,9 +432,13 @@ <string name="zen_modes_dialog_title" msgid="4159138230418567383">"Prioriterade lägen"</string> <string name="zen_modes_dialog_done" msgid="6654130880256438950">"Klar"</string> <string name="zen_modes_dialog_settings" msgid="2310248023728936697">"Inställningar"</string> - <!-- no translation found for zen_mode_on (9085304934016242591) --> + <string name="zen_mode_on" msgid="9085304934016242591">"På"</string> + <string name="zen_mode_off" msgid="1736604456618147306">"Av"</string> + <!-- no translation found for zen_mode_set_up (7457957033034460064) --> <skip /> - <!-- no translation found for zen_mode_off (1736604456618147306) --> + <!-- no translation found for zen_mode_no_manual_invocation (1769975741344633672) --> + <skip /> + <!-- no translation found for zen_mode_active_modes (1625850411578488856) --> <skip /> <string name="zen_priority_introduction" msgid="3159291973383796646">"Du blir inte störd av ljud och vibrationer, förutom från alarm, påminnelser, händelser och specifika samtal. Ljudet är fortfarande på för sådant du väljer att spela upp, till exempel musik, videor och spel."</string> <string name="zen_alarms_introduction" msgid="3987266042682300470">"Du blir inte störd av ljud och vibrationer, förutom från alarm. Ljudet är fortfarande på för sådant du väljer att spela upp, till exempel musik, videor och spel."</string> @@ -471,6 +478,8 @@ <string name="keyguard_indication_charging_time_slowly" msgid="301936949731705417">"<xliff:g id="PERCENTAGE">%2$s</xliff:g> • Laddas långsamt • Fulladdat om <xliff:g id="CHARGING_TIME_LEFT">%1$s</xliff:g>"</string> <string name="keyguard_indication_charging_time_dock" msgid="3149328898931741271">"<xliff:g id="PERCENTAGE">%2$s</xliff:g> • Laddas • Fulladdat om <xliff:g id="CHARGING_TIME_LEFT">%1$s</xliff:g>"</string> <string name="accessibility_action_open_communal_hub" msgid="3081702792413787849">"Widgetar på låsskärmen"</string> + <!-- no translation found for accessibility_announcement_communal_widget_added (6911593106099328271) --> + <skip /> <string name="communal_tutorial_indicator_text" msgid="4503010353591430123">"Svep åt vänster för att börja med gruppguiden"</string> <string name="cta_tile_button_to_open_widget_editor" msgid="3871562362382963878">"Anpassa"</string> <string name="cta_tile_button_to_dismiss" msgid="3377597875997861754">"Ignorera"</string> @@ -499,8 +508,7 @@ <string name="accessibility_action_label_place_widget" msgid="1914197458644168978">"placera vald widget"</string> <string name="communal_widget_picker_title" msgid="1953369090475731663">"Widgetar för låsskärm"</string> <string name="communal_widget_picker_description" msgid="490515450110487871">"Vem som helst kan se widgetar på din låsskärm, även om surfplattan är låst."</string> - <!-- no translation found for accessibility_action_label_unselect_widget (1041811747619468698) --> - <skip /> + <string name="accessibility_action_label_unselect_widget" msgid="1041811747619468698">"avmarkera widget"</string> <string name="communal_widgets_disclaimer_title" msgid="1150954395585308868">"Widgetar för låsskärm"</string> <string name="communal_widgets_disclaimer_text" msgid="1423545475160506349">"Du måste verifiera din identitet innan du öppnar en app med en widget. Tänk också på att alla kan se dem, även när surfplattan är låst. Vissa widgetar kanske inte är avsedda för låsskärmen och det kan vara osäkert att lägga till dem här."</string> <string name="communal_widgets_disclaimer_button" msgid="4423059765740780753">"OK"</string> @@ -557,10 +565,8 @@ <string name="media_projection_action_text" msgid="3634906766918186440">"Starta nu"</string> <string name="empty_shade_text" msgid="8935967157319717412">"Inga aviseringar"</string> <string name="no_unseen_notif_text" msgid="395512586119868682">"Det finns inga nya aviseringar"</string> - <!-- no translation found for adaptive_notification_edu_hun_title (7790738150177329960) --> - <skip /> - <!-- no translation found for adaptive_notification_edu_hun_text (7743367744129536610) --> - <skip /> + <string name="adaptive_notification_edu_hun_title" msgid="7790738150177329960">"Gradvis sänkning för aviseringar är på"</string> + <string name="adaptive_notification_edu_hun_text" msgid="7743367744129536610">"Enheten sänker volymen och minimerar aviseringar i upp till två minuter när du får för många aviseringar samtidigt."</string> <string name="go_to_adaptive_notification_settings" msgid="2423690125178298479">"Inaktivera"</string> <string name="unlock_to_see_notif_text" msgid="7439033907167561227">"Lås upp för att se äldre aviseringar"</string> <string name="quick_settings_disclosure_parental_controls" msgid="2114102871438223600">"Den här enheten hanteras av din förälder"</string> @@ -1226,7 +1232,6 @@ <string name="accessibility_fingerprint_bouncer" msgid="7189102492498735519">"Autentisering krävs. Identifiera dig genom att trycka på fingeravtryckssensorn."</string> <string name="ongoing_phone_call_content_description" msgid="5332334388483099947">"Pågående samtal"</string> <string name="mobile_data_settings_title" msgid="3955246641380064901">"Mobildata"</string> - <string name="preference_summary_default_combination" msgid="8453246369903749670">"<xliff:g id="STATE">%1$s</xliff:g>/<xliff:g id="NETWORKMODE">%2$s</xliff:g>"</string> <string name="mobile_data_connection_active" msgid="944490013299018227">"Ansluten"</string> <string name="mobile_data_temp_connection_active" msgid="4590222725908806824">"Tillfälligt ansluten"</string> <string name="mobile_data_poor_connection" msgid="819617772268371434">"Dålig anslutning"</string> @@ -1380,7 +1385,10 @@ <string name="touchpad_tutorial_done_button" msgid="176168488821755503">"Klar"</string> <string name="touchpad_tutorial_gesture_done" msgid="4784438360736821255">"Bra jobbat!"</string> <string name="touchpad_back_gesture_action_title" msgid="7199067250654332735">"Tillbaka"</string> - <string name="touchpad_back_gesture_guidance" msgid="4222430588599527272">"Gå tillbaka genom att svepa åt vänster eller höger med tre fingrar var som helst på styrplattan."</string> + <!-- no translation found for touchpad_back_gesture_guidance (6263750214998421587) --> + <skip /> + <!-- no translation found for touchpad_back_gesture_finished (5353616006999726249) --> + <skip /> <string name="touchpad_back_gesture_animation_content_description" msgid="2646107450922379918">"Tre fingrar rör sig åt höger och vänster på en styrplatta"</string> <string name="touchpad_back_gesture_screen_animation_content_description" msgid="4036267494237748710">"En enhetsskärm visar en animation för rörelsen Tillbaka"</string> <string name="keyboard_backlight_dialog_title" msgid="8273102932345564724">"Bakgrundsbelysning för tangentbord"</string> @@ -1388,28 +1396,16 @@ <string name="home_controls_dream_label" msgid="6567105701292324257">"Hemstyrning"</string> <string name="home_controls_dream_description" msgid="4644150952104035789">"Kom snabbt åt hemstyrningen via skärmsläckaren"</string> <string name="volume_undo_action" msgid="5815519725211877114">"Ångra"</string> - <!-- no translation found for back_edu_toast_content (4530314597378982956) --> - <skip /> - <!-- no translation found for home_edu_toast_content (3381071147871955415) --> - <skip /> - <!-- no translation found for overview_edu_toast_content (5797030644017804518) --> - <skip /> - <!-- no translation found for all_apps_edu_toast_content (8807496014667211562) --> - <skip /> - <!-- no translation found for back_edu_notification_title (5624780717751357278) --> - <skip /> - <!-- no translation found for back_edu_notification_content (2497557451540954068) --> - <skip /> - <!-- no translation found for home_edu_notification_title (6097902076909654045) --> - <skip /> - <!-- no translation found for home_edu_notification_content (6631697734535766588) --> - <skip /> - <!-- no translation found for overview_edu_notification_title (1265824157319562406) --> - <skip /> - <!-- no translation found for overview_edu_notification_content (3578204677648432500) --> - <skip /> - <!-- no translation found for all_apps_edu_notification_title (372262997265569063) --> - <skip /> - <!-- no translation found for all_apps_edu_notification_content (3255070575694025585) --> - <skip /> + <string name="back_edu_toast_content" msgid="4530314597378982956">"Svep åt höger eller vänster på styrplattan med tre fingrar för att gå tillbaka"</string> + <string name="home_edu_toast_content" msgid="3381071147871955415">"Svep uppåt på styrplattan med tre fingrar för att gå till startskärmen"</string> + <string name="overview_edu_toast_content" msgid="5797030644017804518">"Svep uppåt på styrplattan med tre fingrar och håll kvar för att se nyligen använda appar"</string> + <string name="all_apps_edu_toast_content" msgid="8807496014667211562">"Tryck på åtgärdstangenten på tangentbordet för att se alla appar"</string> + <string name="back_edu_notification_title" msgid="5624780717751357278">"Använd styrplattan för att gå tillbaka"</string> + <string name="back_edu_notification_content" msgid="2497557451540954068">"Svep åt vänster eller höger med tre fingrar. Tryck för att lära dig fler rörelser."</string> + <string name="home_edu_notification_title" msgid="6097902076909654045">"Använd styrplattan för att gå till startskärmen"</string> + <string name="home_edu_notification_content" msgid="6631697734535766588">"Svep uppåt med tre fingrar. Tryck för att lära dig fler rörelser."</string> + <string name="overview_edu_notification_title" msgid="1265824157319562406">"Använd styrplattan för att se nyligen använda appar"</string> + <string name="overview_edu_notification_content" msgid="3578204677648432500">"Svep uppåt med tre fingrar och håll kvar. Tryck för att lära dig fler rörelser."</string> + <string name="all_apps_edu_notification_title" msgid="372262997265569063">"Använd tangentbordet för att se alla appar"</string> + <string name="all_apps_edu_notification_content" msgid="3255070575694025585">"Tryck på åtgärdstangenten när som helst. Tryck för att lära dig fler rörelser."</string> </resources> diff --git a/packages/SystemUI/res/values-sv/tiles_states_strings.xml b/packages/SystemUI/res/values-sv/tiles_states_strings.xml index ba740d5db672..cf49f8db2606 100644 --- a/packages/SystemUI/res/values-sv/tiles_states_strings.xml +++ b/packages/SystemUI/res/values-sv/tiles_states_strings.xml @@ -56,11 +56,6 @@ <item msgid="5376619709702103243">"Av"</item> <item msgid="4875147066469902392">"På"</item> </string-array> - <string-array name="tile_states_modes"> - <item msgid="7764936419245199023">"Inte tillgängliga"</item> - <item msgid="2004750556637773692">"Av"</item> - <item msgid="8968530753931637871">"På"</item> - </string-array> <string-array name="tile_states_flashlight"> <item msgid="3465257127433353857">"Inte tillgängligt"</item> <item msgid="5044688398303285224">"Av"</item> diff --git a/packages/SystemUI/res/values-sw/strings.xml b/packages/SystemUI/res/values-sw/strings.xml index faaa1c484ebc..d3e4e5d21e98 100644 --- a/packages/SystemUI/res/values-sw/strings.xml +++ b/packages/SystemUI/res/values-sw/strings.xml @@ -132,17 +132,17 @@ <string name="screenrecord_stop_dialog_button" msgid="2883812564938194350">"Acha kurekodi"</string> <string name="share_to_app_chip_accessibility_label" msgid="4210256229976947065">"Inaruhusu ufikiaji kwenye skrini"</string> <string name="share_to_app_stop_dialog_title" msgid="9212915050910250438">"Ungependa kuacha kuonyesha skrini?"</string> - <string name="share_to_app_stop_dialog_message_entire_screen_with_host_app" msgid="522823522115375414">"Kwa sasa unatuma skrini yako nzima kwenye <xliff:g id="HOST_APP_NAME">%1$s</xliff:g>"</string> - <string name="share_to_app_stop_dialog_message_entire_screen" msgid="5090115386271179270">"Kwa sasa unatuma skrini yako nzima kwenye programu"</string> - <string name="share_to_app_stop_dialog_message_single_app_specific" msgid="5923772039347985172">"Kwa sasa unatuma <xliff:g id="APP_BEING_SHARED_NAME">%1$s</xliff:g>"</string> - <string name="share_to_app_stop_dialog_message_single_app_generic" msgid="6681016774654578261">"Kwa sasa unatuma programu"</string> + <string name="share_to_app_stop_dialog_message_entire_screen_with_host_app" msgid="522823522115375414">"Kwa sasa unatuma maudhui yaliyo katika skrini yako nzima kwenye <xliff:g id="HOST_APP_NAME">%1$s</xliff:g>"</string> + <string name="share_to_app_stop_dialog_message_entire_screen" msgid="5090115386271179270">"Kwa sasa unatuma maudhui yaliyo katika skrini yako nzima kwenye programu"</string> + <string name="share_to_app_stop_dialog_message_single_app_specific" msgid="5923772039347985172">"Kwa sasa unatumia <xliff:g id="APP_BEING_SHARED_NAME">%1$s</xliff:g> pamoja na wengine"</string> + <string name="share_to_app_stop_dialog_message_single_app_generic" msgid="6681016774654578261">"Kwa sasa unatumia programu pamoja na wengine"</string> <string name="share_to_app_stop_dialog_button" msgid="6334056916284230217">"Acha kuonyesha skrini"</string> <string name="cast_screen_to_other_device_chip_accessibility_label" msgid="4687917476203009885">"Inatuma skrini"</string> <string name="cast_to_other_device_stop_dialog_title" msgid="7836517190930357326">"Ungependa kuacha kutuma?"</string> - <string name="cast_to_other_device_stop_dialog_message_entire_screen_with_device" msgid="1474703115926205251">"Kwa sasa unatuma skrini yako nzima kwenye <xliff:g id="DEVICE_NAME">%1$s</xliff:g>"</string> - <string name="cast_to_other_device_stop_dialog_message_entire_screen" msgid="8419219169553867625">"Kwa sasa unatuma skrini yako nzima kwenye kifaa kilicho karibu"</string> - <string name="cast_to_other_device_stop_dialog_message_specific_app_with_device" msgid="2715934698604085519">"Kwa sasa unatuma <xliff:g id="APP_BEING_SHARED_NAME">%1$s</xliff:g> kwenye <xliff:g id="DEVICE_NAME">%2$s</xliff:g>"</string> - <string name="cast_to_other_device_stop_dialog_message_specific_app" msgid="8616103075630934513">"Kwa sasa unatuma <xliff:g id="APP_BEING_SHARED_NAME">%1$s</xliff:g> kwenye kifaa kilicho karibu"</string> + <string name="cast_to_other_device_stop_dialog_message_entire_screen_with_device" msgid="1474703115926205251">"Kwa sasa unatuma maudhui yaliyo katika skrini yako nzima kwenye <xliff:g id="DEVICE_NAME">%1$s</xliff:g>"</string> + <string name="cast_to_other_device_stop_dialog_message_entire_screen" msgid="8419219169553867625">"Kwa sasa unatuma maudhui yaliyo katika skrini yako nzima kwenye kifaa kilicho karibu"</string> + <string name="cast_to_other_device_stop_dialog_message_specific_app_with_device" msgid="2715934698604085519">"Kwa sasa unatuma maudhui yaliyo katika <xliff:g id="APP_BEING_SHARED_NAME">%1$s</xliff:g> kwenye <xliff:g id="DEVICE_NAME">%2$s</xliff:g>"</string> + <string name="cast_to_other_device_stop_dialog_message_specific_app" msgid="8616103075630934513">"Kwa sasa unatuma maudhui yaliyo katika <xliff:g id="APP_BEING_SHARED_NAME">%1$s</xliff:g> kwenye kifaa kilicho karibu"</string> <string name="cast_to_other_device_stop_dialog_message_generic_with_device" msgid="9213582497852420203">"Kwa sasa unatuma maudhui kwenye <xliff:g id="DEVICE_NAME">%1$s</xliff:g>"</string> <string name="cast_to_other_device_stop_dialog_message_generic" msgid="4100272100480415076">"Kwa sasa unatuma maudhui kwenye kifaa kilicho karibu"</string> <string name="cast_to_other_device_stop_dialog_button" msgid="6420183747435521834">"Acha kutuma maudhui"</string> @@ -388,6 +388,9 @@ <string name="performance" msgid="6552785217174378320">"Utendaji"</string> <string name="user_interface" msgid="3712869377953950887">"Kiolesura"</string> <string name="thermal" msgid="6758074791325414831">"Joto"</string> + <string name="custom" msgid="3337456985275158299">"Maalum"</string> + <string name="custom_trace_settings_dialog_title" msgid="2608570500144830554">"Mipangilio Maalum ya Historia ya Shughuli"</string> + <string name="restore_default" msgid="5259420807486239755">"Rejesha Mipangilio Chaguomsingi"</string> <string name="quick_settings_onehanded_label" msgid="2416537930246274991">"Hali ya kutumia kwa mkono mmoja"</string> <string name="quick_settings_hearing_devices_label" msgid="7277170419679404129">"Vifaa vya kusikilizia"</string> <string name="quick_settings_hearing_devices_connected" msgid="6519069502397037781">"Vimeunganishwa"</string> @@ -429,9 +432,13 @@ <string name="zen_modes_dialog_title" msgid="4159138230418567383">"Hali za kipaumbele"</string> <string name="zen_modes_dialog_done" msgid="6654130880256438950">"Nimemaliza"</string> <string name="zen_modes_dialog_settings" msgid="2310248023728936697">"Mipangilio"</string> - <!-- no translation found for zen_mode_on (9085304934016242591) --> + <string name="zen_mode_on" msgid="9085304934016242591">"Imewashwa"</string> + <string name="zen_mode_off" msgid="1736604456618147306">"Imezimwa"</string> + <!-- no translation found for zen_mode_set_up (7457957033034460064) --> <skip /> - <!-- no translation found for zen_mode_off (1736604456618147306) --> + <!-- no translation found for zen_mode_no_manual_invocation (1769975741344633672) --> + <skip /> + <!-- no translation found for zen_mode_active_modes (1625850411578488856) --> <skip /> <string name="zen_priority_introduction" msgid="3159291973383796646">"Hutasumbuliwa na sauti na mitetemo, isipokuwa kengele, vikumbusho, matukio na simu zinazopigwa na watu uliobainisha. Bado utasikia chochote utakachochagua kucheza, ikiwa ni pamoja na muziki, video na michezo."</string> <string name="zen_alarms_introduction" msgid="3987266042682300470">"Hutasumbuliwa na sauti na mitetemo, isipokuwa kengele. Bado utasikia chochote utakachochagua kucheza, ikiwa ni pamoja na muziki, video na michezo."</string> @@ -471,6 +478,8 @@ <string name="keyguard_indication_charging_time_slowly" msgid="301936949731705417">"<xliff:g id="PERCENTAGE">%2$s</xliff:g> • Inachaji polepole • Itajaa baada ya <xliff:g id="CHARGING_TIME_LEFT">%1$s</xliff:g>"</string> <string name="keyguard_indication_charging_time_dock" msgid="3149328898931741271">"<xliff:g id="PERCENTAGE">%2$s</xliff:g> • Inachaji • Itajaa baada ya <xliff:g id="CHARGING_TIME_LEFT">%1$s</xliff:g>"</string> <string name="accessibility_action_open_communal_hub" msgid="3081702792413787849">"Wijeti kwenye skrini iliyofungwa"</string> + <!-- no translation found for accessibility_announcement_communal_widget_added (6911593106099328271) --> + <skip /> <string name="communal_tutorial_indicator_text" msgid="4503010353591430123">"Telezesha kidole kushoto ili uanze mafunzo ya pamoja"</string> <string name="cta_tile_button_to_open_widget_editor" msgid="3871562362382963878">"Weka mapendeleo"</string> <string name="cta_tile_button_to_dismiss" msgid="3377597875997861754">"Funga"</string> @@ -499,8 +508,7 @@ <string name="accessibility_action_label_place_widget" msgid="1914197458644168978">"weka wijeti uliyochagua"</string> <string name="communal_widget_picker_title" msgid="1953369090475731663">"Wijeti zinazoonekana kwenye skrini iliyofungwa"</string> <string name="communal_widget_picker_description" msgid="490515450110487871">"Yeyote anaweza kuona wijeti kwenye skrini yako iliyofungwa, hata ikiwa umefunga kishikwambi chako."</string> - <!-- no translation found for accessibility_action_label_unselect_widget (1041811747619468698) --> - <skip /> + <string name="accessibility_action_label_unselect_widget" msgid="1041811747619468698">"acha kuchagua wijeti"</string> <string name="communal_widgets_disclaimer_title" msgid="1150954395585308868">"Wijeti zinazoonekana kwenye skrini iliyofungwa"</string> <string name="communal_widgets_disclaimer_text" msgid="1423545475160506349">"Utahitaji kuthibitisha kuwa ni wewe ili ufungue programu ukitumia wijeti. Pia, kumbuka kuwa mtu yeyote anaweza kuziona, hata kishikwambi chako kikiwa kimefungwa. Huenda baadhi ya wijeti hazikukusudiwa kutumika kwenye skrini yako iliyofungwa na huenda si salama kuziweka hapa."</string> <string name="communal_widgets_disclaimer_button" msgid="4423059765740780753">"Nimeelewa"</string> @@ -557,10 +565,8 @@ <string name="media_projection_action_text" msgid="3634906766918186440">"Anza sasa"</string> <string name="empty_shade_text" msgid="8935967157319717412">"Hakuna arifa"</string> <string name="no_unseen_notif_text" msgid="395512586119868682">"Hakuna arifa mpya"</string> - <!-- no translation found for adaptive_notification_edu_hun_title (7790738150177329960) --> - <skip /> - <!-- no translation found for adaptive_notification_edu_hun_text (7743367744129536610) --> - <skip /> + <string name="adaptive_notification_edu_hun_title" msgid="7790738150177329960">"Umewasha mipangilio ya kutuliza arifa"</string> + <string name="adaptive_notification_edu_hun_text" msgid="7743367744129536610">"Arifa na sauti hupunguzwa kiotomatiki kwenye kifaa chako kwa hadi dakika 2 unapopokea arifa nyingi kwa wakati mmoja."</string> <string name="go_to_adaptive_notification_settings" msgid="2423690125178298479">"Zima"</string> <string name="unlock_to_see_notif_text" msgid="7439033907167561227">"Fungua ili uone arifa za zamani"</string> <string name="quick_settings_disclosure_parental_controls" msgid="2114102871438223600">"Kifaa hiki kinadhibitiwa na mzazi wako"</string> @@ -1226,7 +1232,6 @@ <string name="accessibility_fingerprint_bouncer" msgid="7189102492498735519">"Uthibitishaji unahitajika. Gusa kitambua alama ya kidole ili uthibitishe."</string> <string name="ongoing_phone_call_content_description" msgid="5332334388483099947">"Simu inayoendelea"</string> <string name="mobile_data_settings_title" msgid="3955246641380064901">"Data ya mtandao wa simu"</string> - <string name="preference_summary_default_combination" msgid="8453246369903749670">"<xliff:g id="STATE">%1$s</xliff:g> / <xliff:g id="NETWORKMODE">%2$s</xliff:g>"</string> <string name="mobile_data_connection_active" msgid="944490013299018227">"Imeunganishwa"</string> <string name="mobile_data_temp_connection_active" msgid="4590222725908806824">"Imeunganishwa kwa muda"</string> <string name="mobile_data_poor_connection" msgid="819617772268371434">"Muunganisho duni"</string> @@ -1380,7 +1385,10 @@ <string name="touchpad_tutorial_done_button" msgid="176168488821755503">"Nimemaliza"</string> <string name="touchpad_tutorial_gesture_done" msgid="4784438360736821255">"Kazi nzuri!"</string> <string name="touchpad_back_gesture_action_title" msgid="7199067250654332735">"Rudi nyuma"</string> - <string name="touchpad_back_gesture_guidance" msgid="4222430588599527272">"Ili kurudi nyuma, telezesha vidole vitatu kushoto au kulia mahali popote kwenye padi ya kugusa."</string> + <!-- no translation found for touchpad_back_gesture_guidance (6263750214998421587) --> + <skip /> + <!-- no translation found for touchpad_back_gesture_finished (5353616006999726249) --> + <skip /> <string name="touchpad_back_gesture_animation_content_description" msgid="2646107450922379918">"Padi ya kugusa inayoonyesha vidole vitatu vikisonga kulia na kushoto"</string> <string name="touchpad_back_gesture_screen_animation_content_description" msgid="4036267494237748710">"Skrini ya kifaa inayoonyesha uhuishaji wa mguso wa nyuma"</string> <string name="keyboard_backlight_dialog_title" msgid="8273102932345564724">"Mwanga chini ya kibodi"</string> @@ -1388,28 +1396,16 @@ <string name="home_controls_dream_label" msgid="6567105701292324257">"Dhibiti Vifaa Nyumbani"</string> <string name="home_controls_dream_description" msgid="4644150952104035789">"Fikia haraka vidhibiti vya vifaa nyumbani vikiwa taswira ya skrini"</string> <string name="volume_undo_action" msgid="5815519725211877114">"Tendua"</string> - <!-- no translation found for back_edu_toast_content (4530314597378982956) --> - <skip /> - <!-- no translation found for home_edu_toast_content (3381071147871955415) --> - <skip /> - <!-- no translation found for overview_edu_toast_content (5797030644017804518) --> - <skip /> - <!-- no translation found for all_apps_edu_toast_content (8807496014667211562) --> - <skip /> - <!-- no translation found for back_edu_notification_title (5624780717751357278) --> - <skip /> - <!-- no translation found for back_edu_notification_content (2497557451540954068) --> - <skip /> - <!-- no translation found for home_edu_notification_title (6097902076909654045) --> - <skip /> - <!-- no translation found for home_edu_notification_content (6631697734535766588) --> - <skip /> - <!-- no translation found for overview_edu_notification_title (1265824157319562406) --> - <skip /> - <!-- no translation found for overview_edu_notification_content (3578204677648432500) --> - <skip /> - <!-- no translation found for all_apps_edu_notification_title (372262997265569063) --> - <skip /> - <!-- no translation found for all_apps_edu_notification_content (3255070575694025585) --> - <skip /> + <string name="back_edu_toast_content" msgid="4530314597378982956">"Telezesha vidole vitatu kutoka kushoto au kulia kwenye padi ya kugusa ili urudi nyuma"</string> + <string name="home_edu_toast_content" msgid="3381071147871955415">"Telezesha vidole vitatu juu kwenye padi ya kugusa ili urudi kwenye skrini ya kwanza"</string> + <string name="overview_edu_toast_content" msgid="5797030644017804518">"Telezesha vidole vitatu juu na ushikilie kwenye padi ya kugusa ili uangalie programu za hivi majuzi"</string> + <string name="all_apps_edu_toast_content" msgid="8807496014667211562">"Bonyeza kitufe cha vitendo kwenye kibodi yako ili uangalie programu zako zote"</string> + <string name="back_edu_notification_title" msgid="5624780717751357278">"Kutumia padi yako ya kugusa ili kurudi nyuma"</string> + <string name="back_edu_notification_content" msgid="2497557451540954068">"Telezesha vidole vitatu kulia au kushoto. Gusa ili upate maelezo kuhusu miguso zaidi."</string> + <string name="home_edu_notification_title" msgid="6097902076909654045">"Kutumia padi yako ya kugusa ili kurudi kwenye skrini ya kwanza"</string> + <string name="home_edu_notification_content" msgid="6631697734535766588">"Telezesha vidole vitatu juu. Gusa ili upate maelezo kuhusu miguso zaidi."</string> + <string name="overview_edu_notification_title" msgid="1265824157319562406">"Kutumia padi yako ya kugusa ili kuangalia programu za hivi majuzi"</string> + <string name="overview_edu_notification_content" msgid="3578204677648432500">"Telezesha vidole vitatu juu na ushikilie. Gusa ili upate maelezo kuhusu miguso zaidi."</string> + <string name="all_apps_edu_notification_title" msgid="372262997265569063">"Kutumia kibodi yako kuangalia programu zote"</string> + <string name="all_apps_edu_notification_content" msgid="3255070575694025585">"Bonyeza kitufe cha vitendo wakati wowote. Gusa ili upate maelezo kuhusu miguso zaidi."</string> </resources> diff --git a/packages/SystemUI/res/values-sw/tiles_states_strings.xml b/packages/SystemUI/res/values-sw/tiles_states_strings.xml index 369d56ac8fd9..15de7f88694c 100644 --- a/packages/SystemUI/res/values-sw/tiles_states_strings.xml +++ b/packages/SystemUI/res/values-sw/tiles_states_strings.xml @@ -56,11 +56,6 @@ <item msgid="5376619709702103243">"Kimezimwa"</item> <item msgid="4875147066469902392">"Kimewashwa"</item> </string-array> - <string-array name="tile_states_modes"> - <item msgid="7764936419245199023">"Haipatikani"</item> - <item msgid="2004750556637773692">"Imezimwa"</item> - <item msgid="8968530753931637871">"Imewashwa"</item> - </string-array> <string-array name="tile_states_flashlight"> <item msgid="3465257127433353857">"Hakipatikani"</item> <item msgid="5044688398303285224">"Kimezimwa"</item> diff --git a/packages/SystemUI/res/values-ta/strings.xml b/packages/SystemUI/res/values-ta/strings.xml index 414d0a713115..6cef518d194f 100644 --- a/packages/SystemUI/res/values-ta/strings.xml +++ b/packages/SystemUI/res/values-ta/strings.xml @@ -388,6 +388,9 @@ <string name="performance" msgid="6552785217174378320">"செயல்திறன்"</string> <string name="user_interface" msgid="3712869377953950887">"பயனர் இடைமுகம்"</string> <string name="thermal" msgid="6758074791325414831">"தெர்மல்"</string> + <string name="custom" msgid="3337456985275158299">"பிரத்தியேகம்"</string> + <string name="custom_trace_settings_dialog_title" msgid="2608570500144830554">"பிரத்தியேக டிரேஸ் அமைப்புகள்"</string> + <string name="restore_default" msgid="5259420807486239755">"இயல்புக்கு மீட்டெடு"</string> <string name="quick_settings_onehanded_label" msgid="2416537930246274991">"ஒற்றைக் கைப் பயன்முறை"</string> <string name="quick_settings_hearing_devices_label" msgid="7277170419679404129">"செவித்துணைக் கருவிகள்"</string> <string name="quick_settings_hearing_devices_connected" msgid="6519069502397037781">"செயலில் உள்ளது"</string> @@ -429,9 +432,13 @@ <string name="zen_modes_dialog_title" msgid="4159138230418567383">"முன்னுரிமைப் பயன்முறைகள்"</string> <string name="zen_modes_dialog_done" msgid="6654130880256438950">"முடிந்தது"</string> <string name="zen_modes_dialog_settings" msgid="2310248023728936697">"அமைப்புகள்"</string> - <!-- no translation found for zen_mode_on (9085304934016242591) --> + <string name="zen_mode_on" msgid="9085304934016242591">"இயக்கப்பட்டுள்ளது"</string> + <string name="zen_mode_off" msgid="1736604456618147306">"முடக்கப்பட்டுள்ளது"</string> + <!-- no translation found for zen_mode_set_up (7457957033034460064) --> <skip /> - <!-- no translation found for zen_mode_off (1736604456618147306) --> + <!-- no translation found for zen_mode_no_manual_invocation (1769975741344633672) --> + <skip /> + <!-- no translation found for zen_mode_active_modes (1625850411578488856) --> <skip /> <string name="zen_priority_introduction" msgid="3159291973383796646">"அலாரங்கள், நினைவூட்டல்கள், நிகழ்வுகள் மற்றும் குறிப்பிட்ட அழைப்பாளர்களைத் தவிர்த்து, பிற ஒலிகள் மற்றும் அதிர்வுகளின் தொந்தரவு இருக்காது. எனினும், நீங்கள் எதையேனும் (இசை, வீடியோக்கள், கேம்ஸ் போன்றவை) ஒலிக்கும்படி தேர்ந்தெடுத்திருந்தால், அவை வழக்கம் போல் ஒலிக்கும்."</string> <string name="zen_alarms_introduction" msgid="3987266042682300470">"அலாரங்களைத் தவிர்த்து, பிற ஒலிகள் மற்றும் அதிர்வுகளின் தொந்தரவு இருக்காது. எனினும், நீங்கள் எதையேனும் (இசை, வீடியோக்கள், கேம்ஸ் போன்றவை) ஒலிக்கும்படி தேர்ந்தெடுத்திருந்தால், அவை வழக்கம் போல் ஒலிக்கும்."</string> @@ -471,6 +478,8 @@ <string name="keyguard_indication_charging_time_slowly" msgid="301936949731705417">"<xliff:g id="PERCENTAGE">%2$s</xliff:g> • மெதுவாக சார்ஜாகிறது • <xliff:g id="CHARGING_TIME_LEFT">%1$s</xliff:g> இல் முழுதும் சார்ஜாகும்"</string> <string name="keyguard_indication_charging_time_dock" msgid="3149328898931741271">"<xliff:g id="PERCENTAGE">%2$s</xliff:g> • சார்ஜாகிறது • <xliff:g id="CHARGING_TIME_LEFT">%1$s</xliff:g> இல் முழுவதும் சார்ஜாகும்"</string> <string name="accessibility_action_open_communal_hub" msgid="3081702792413787849">"பூட்டுத் திரையில் விட்ஜெட்கள்"</string> + <!-- no translation found for accessibility_announcement_communal_widget_added (6911593106099328271) --> + <skip /> <string name="communal_tutorial_indicator_text" msgid="4503010353591430123">"சமூகப் பயிற்சியைத் தொடங்க இடதுபுறம் ஸ்வைப் செய்யுங்கள்"</string> <string name="cta_tile_button_to_open_widget_editor" msgid="3871562362382963878">"பிரத்தியேகமாக்குங்கள்"</string> <string name="cta_tile_button_to_dismiss" msgid="3377597875997861754">"மூடுக"</string> @@ -499,8 +508,7 @@ <string name="accessibility_action_label_place_widget" msgid="1914197458644168978">"தேர்ந்தெடுத்த விட்ஜெட்டைக் காட்சிப்படுத்தும்"</string> <string name="communal_widget_picker_title" msgid="1953369090475731663">"பூட்டுத் திரை விட்ஜெட்கள்"</string> <string name="communal_widget_picker_description" msgid="490515450110487871">"டேப்லெட் பூட்டப்பட்டிருந்தாலும் பூட்டுத் திரையில் விட்ஜெட்டை எவரும் பார்க்கலாம்."</string> - <!-- no translation found for accessibility_action_label_unselect_widget (1041811747619468698) --> - <skip /> + <string name="accessibility_action_label_unselect_widget" msgid="1041811747619468698">"விட்ஜெட்டைத் தேர்வுநீக்கும்"</string> <string name="communal_widgets_disclaimer_title" msgid="1150954395585308868">"பூட்டுத் திரை விட்ஜெட்கள்"</string> <string name="communal_widgets_disclaimer_text" msgid="1423545475160506349">"விட்ஜெட்டைப் பயன்படுத்தி ஆப்ஸைத் திறக்க, அது நீங்கள்தான் என்பதை உறுதிசெய்ய வேண்டும். அத்துடன், உங்கள் டேப்லெட் பூட்டப்பட்டிருந்தாலும்கூட அவற்றை யார் வேண்டுமானாலும் பார்க்கலாம் என்பதை நினைவில்கொள்ளுங்கள். சில விட்ஜெட்கள் உங்கள் பூட்டுத் திரைக்காக உருவாக்கப்பட்டவை அல்ல என்பதையும் அவற்றை இங்கே சேர்ப்பது பாதுகாப்பற்றதாக இருக்கக்கூடும் என்பதையும் நினைவில்கொள்ளுங்கள்."</string> <string name="communal_widgets_disclaimer_button" msgid="4423059765740780753">"சரி"</string> @@ -557,10 +565,8 @@ <string name="media_projection_action_text" msgid="3634906766918186440">"இப்போது தொடங்கு"</string> <string name="empty_shade_text" msgid="8935967157319717412">"அறிவிப்புகள் இல்லை"</string> <string name="no_unseen_notif_text" msgid="395512586119868682">"புதிய அறிவிப்புகள் இல்லை"</string> - <!-- no translation found for adaptive_notification_edu_hun_title (7790738150177329960) --> - <skip /> - <!-- no translation found for adaptive_notification_edu_hun_text (7743367744129536610) --> - <skip /> + <string name="adaptive_notification_edu_hun_title" msgid="7790738150177329960">"\'குறைந்த ஒலியளவில் அறிவிப்புகள்\' இயக்கப்பட்டுள்ளது"</string> + <string name="adaptive_notification_edu_hun_text" msgid="7743367744129536610">"ஒரே நேரம் பல அறிவிப்புகள் வரும்போது சாதன ஒலியளவும் விழிப்பூட்டலும் தானாக 2 நிமிடம் குறைக்கப்படும்."</string> <string name="go_to_adaptive_notification_settings" msgid="2423690125178298479">"முடக்கு"</string> <string name="unlock_to_see_notif_text" msgid="7439033907167561227">"பழைய அறிவிப்பைப் பார்க்க அன்லாக் செய்க"</string> <string name="quick_settings_disclosure_parental_controls" msgid="2114102871438223600">"இந்தச் சாதனம் உங்கள் பெற்றோரால் நிர்வகிக்கப்படுகிறது"</string> @@ -1226,7 +1232,6 @@ <string name="accessibility_fingerprint_bouncer" msgid="7189102492498735519">"அங்கீகாரம் தேவை. கைரேகை சென்சாரைத் தொட்டு அங்கீகரியுங்கள்."</string> <string name="ongoing_phone_call_content_description" msgid="5332334388483099947">"செயலில் உள்ள மொபைல் அழைப்பு"</string> <string name="mobile_data_settings_title" msgid="3955246641380064901">"மொபைல் டேட்டா"</string> - <string name="preference_summary_default_combination" msgid="8453246369903749670">"<xliff:g id="STATE">%1$s</xliff:g> / <xliff:g id="NETWORKMODE">%2$s</xliff:g>"</string> <string name="mobile_data_connection_active" msgid="944490013299018227">"இணைக்கப்பட்டது"</string> <string name="mobile_data_temp_connection_active" msgid="4590222725908806824">"தற்காலிகமாக இணைக்கப்பட்டுள்ளது"</string> <string name="mobile_data_poor_connection" msgid="819617772268371434">"இணைப்பு மோசமாக உள்ளது"</string> @@ -1380,7 +1385,10 @@ <string name="touchpad_tutorial_done_button" msgid="176168488821755503">"முடிந்தது"</string> <string name="touchpad_tutorial_gesture_done" msgid="4784438360736821255">"அருமை!"</string> <string name="touchpad_back_gesture_action_title" msgid="7199067250654332735">"பின்செல்"</string> - <string name="touchpad_back_gesture_guidance" msgid="4222430588599527272">"பின்செல்ல, உங்கள் டச்பேடில் எங்கு வேண்டுமானாலும் இடது அல்லது வலதுபுறமாக மூன்று விரல்களால் ஸ்வைப் செய்யவும்."</string> + <!-- no translation found for touchpad_back_gesture_guidance (6263750214998421587) --> + <skip /> + <!-- no translation found for touchpad_back_gesture_finished (5353616006999726249) --> + <skip /> <string name="touchpad_back_gesture_animation_content_description" msgid="2646107450922379918">"மூன்று விரல்கள் வலது மற்றும் இடதுபுறம் நகர்வதை டச்பேட் காட்டுகிறது"</string> <string name="touchpad_back_gesture_screen_animation_content_description" msgid="4036267494237748710">"பின்செல்லும் சைகைக்கான அனிமேஷனை சாதனத்தின் திரை காட்டுகிறது"</string> <string name="keyboard_backlight_dialog_title" msgid="8273102932345564724">"கீபோர்டு பேக்லைட்"</string> @@ -1388,28 +1396,16 @@ <string name="home_controls_dream_label" msgid="6567105701292324257">"ஹோம் கன்ட்ரோல்கள்"</string> <string name="home_controls_dream_description" msgid="4644150952104035789">"ஹோம் கன்ட்ரோல்களை ஸ்கிரீன் சேவராக அணுகலாம்"</string> <string name="volume_undo_action" msgid="5815519725211877114">"செயல்தவிர்"</string> - <!-- no translation found for back_edu_toast_content (4530314597378982956) --> - <skip /> - <!-- no translation found for home_edu_toast_content (3381071147871955415) --> - <skip /> - <!-- no translation found for overview_edu_toast_content (5797030644017804518) --> - <skip /> - <!-- no translation found for all_apps_edu_toast_content (8807496014667211562) --> - <skip /> - <!-- no translation found for back_edu_notification_title (5624780717751357278) --> - <skip /> - <!-- no translation found for back_edu_notification_content (2497557451540954068) --> - <skip /> - <!-- no translation found for home_edu_notification_title (6097902076909654045) --> - <skip /> - <!-- no translation found for home_edu_notification_content (6631697734535766588) --> - <skip /> - <!-- no translation found for overview_edu_notification_title (1265824157319562406) --> - <skip /> - <!-- no translation found for overview_edu_notification_content (3578204677648432500) --> - <skip /> - <!-- no translation found for all_apps_edu_notification_title (372262997265569063) --> - <skip /> - <!-- no translation found for all_apps_edu_notification_content (3255070575694025585) --> - <skip /> + <string name="back_edu_toast_content" msgid="4530314597378982956">"பின்செல்ல, உங்கள் டச்பேடில் இடது அல்லது வலதுபுறமாக மூன்று விரல்களால் ஸ்வைப் செய்யவும்"</string> + <string name="home_edu_toast_content" msgid="3381071147871955415">"முகப்புக்குச் செல்ல, உங்கள் டச்பேடில் மூன்று விரல்களால் மேல்நோக்கி ஸ்வைப் செய்யவும்"</string> + <string name="overview_edu_toast_content" msgid="5797030644017804518">"சமீபத்திய ஆப்ஸைப் பார்க்க, டச்பேடில் மூன்று விரல்களால் மேல்நோக்கி ஸ்வைப் செய்து பிடிக்கவும்"</string> + <string name="all_apps_edu_toast_content" msgid="8807496014667211562">"அனைத்து ஆப்ஸையும் பார்க்க, உங்கள் கீபோர்டில் உள்ள ஆக்ஷன் பட்டனை அழுத்தவும்"</string> + <string name="back_edu_notification_title" msgid="5624780717751357278">"பின்செல்ல, உங்கள் டச்பேடைப் பயன்படுத்துங்கள்"</string> + <string name="back_edu_notification_content" msgid="2497557451540954068">"மூன்று விரல்களால் இடது அல்லது வலதுபுறம் ஸ்வைப் செய்யவும். சைகைகள் குறித்து மேலும் அறிய தட்டவும்."</string> + <string name="home_edu_notification_title" msgid="6097902076909654045">"முகப்புக்குச் செல்ல, உங்கள் டச்பேடைப் பயன்படுத்துங்கள்"</string> + <string name="home_edu_notification_content" msgid="6631697734535766588">"மூன்று விரல்களால் மேல்நோக்கி ஸ்வைப் செய்யவும். சைகைகள் குறித்து மேலும் அறிய தட்டவும்."</string> + <string name="overview_edu_notification_title" msgid="1265824157319562406">"சமீபத்திய ஆப்ஸைப் பார்க்க, உங்கள் டச்பேடைப் பயன்படுத்துங்கள்"</string> + <string name="overview_edu_notification_content" msgid="3578204677648432500">"மூன்று விரல்களால் மேல்நோக்கி ஸ்வைப் செய்து பிடிக்கவும். சைகைகள் குறித்து மேலும் அறிய தட்டவும்."</string> + <string name="all_apps_edu_notification_title" msgid="372262997265569063">"அனைத்து ஆப்ஸையும் பார்க்க உங்கள் கீபோர்டைப் பயன்படுத்துங்கள்"</string> + <string name="all_apps_edu_notification_content" msgid="3255070575694025585">"எப்போது வேண்டுமானாலும் ஆக்ஷன் பட்டனை அழுத்தலாம். சைகைகள் குறித்து மேலும் அறிய தட்டவும்."</string> </resources> diff --git a/packages/SystemUI/res/values-ta/tiles_states_strings.xml b/packages/SystemUI/res/values-ta/tiles_states_strings.xml index 9f23d0af0c06..a3b9538f891c 100644 --- a/packages/SystemUI/res/values-ta/tiles_states_strings.xml +++ b/packages/SystemUI/res/values-ta/tiles_states_strings.xml @@ -56,11 +56,6 @@ <item msgid="5376619709702103243">"முடக்கப்பட்டுள்ளது"</item> <item msgid="4875147066469902392">"இயக்கப்பட்டுள்ளது"</item> </string-array> - <string-array name="tile_states_modes"> - <item msgid="7764936419245199023">"இல்லை"</item> - <item msgid="2004750556637773692">"முடக்கப்பட்டுள்ளது"</item> - <item msgid="8968530753931637871">"இயக்கப்பட்டுள்ளது"</item> - </string-array> <string-array name="tile_states_flashlight"> <item msgid="3465257127433353857">"கிடைக்கவில்லை"</item> <item msgid="5044688398303285224">"முடக்கப்பட்டுள்ளது"</item> diff --git a/packages/SystemUI/res/values-te/strings.xml b/packages/SystemUI/res/values-te/strings.xml index 1b1d6080d710..e9cb6ebc53cc 100644 --- a/packages/SystemUI/res/values-te/strings.xml +++ b/packages/SystemUI/res/values-te/strings.xml @@ -388,6 +388,9 @@ <string name="performance" msgid="6552785217174378320">"పనితీరు"</string> <string name="user_interface" msgid="3712869377953950887">"యూజర్ ఇంటర్ఫేస్"</string> <string name="thermal" msgid="6758074791325414831">"థర్మల్"</string> + <string name="custom" msgid="3337456985275158299">"అనుకూలంగా మార్చుకోండి"</string> + <string name="custom_trace_settings_dialog_title" msgid="2608570500144830554">"కస్టమ్ ట్రేస్ సెట్టింగ్లు"</string> + <string name="restore_default" msgid="5259420807486239755">"డిఫాల్ట్ను రీస్టోర్ చేయండి"</string> <string name="quick_settings_onehanded_label" msgid="2416537930246274991">"వన్-హ్యాండెడ్ మోడ్"</string> <string name="quick_settings_hearing_devices_label" msgid="7277170419679404129">"వినికిడి పరికరాలు"</string> <string name="quick_settings_hearing_devices_connected" msgid="6519069502397037781">"యాక్టివ్"</string> @@ -429,10 +432,11 @@ <string name="zen_modes_dialog_title" msgid="4159138230418567383">"ముఖ్యమైన ఫైళ్ల మోడ్స్"</string> <string name="zen_modes_dialog_done" msgid="6654130880256438950">"పూర్తయింది"</string> <string name="zen_modes_dialog_settings" msgid="2310248023728936697">"సెట్టింగ్లు"</string> - <!-- no translation found for zen_mode_on (9085304934016242591) --> - <skip /> - <!-- no translation found for zen_mode_off (1736604456618147306) --> - <skip /> + <string name="zen_mode_on" msgid="9085304934016242591">"ఆన్లో ఉంది"</string> + <string name="zen_mode_off" msgid="1736604456618147306">"ఆఫ్లో ఉంది"</string> + <string name="zen_mode_set_up" msgid="7457957033034460064">"సెటప్ చేయండి"</string> + <string name="zen_mode_no_manual_invocation" msgid="1769975741344633672">"సెట్టింగ్లలో మేనేజ్ చేయండి"</string> + <string name="zen_mode_active_modes" msgid="1625850411578488856">"{count,plural, =0{మోడ్స్ ఏవీ యాక్టివ్గా లేవు}=1{{mode} యాక్టివ్గా ఉంది}other{# మోడ్స్ యాక్టివ్గా ఉన్నాయి}}"</string> <string name="zen_priority_introduction" msgid="3159291973383796646">"మీరు పేర్కొనే అలారాలు, రిమైండర్లు, ఈవెంట్లు మరియు కాలర్ల నుండి మినహా మరే ఇతర ధ్వనులు మరియు వైబ్రేషన్లతో మీకు అంతరాయం కలగదు. మీరు ఇప్పటికీ సంగీతం, వీడియోలు మరియు గేమ్లతో సహా మీరు ప్లే చేయడానికి ఎంచుకున్నవి ఏవైనా వింటారు."</string> <string name="zen_alarms_introduction" msgid="3987266042682300470">"అలారాలు నుండి మినహా మరే ఇతర ధ్వనులు మరియు వైబ్రేషన్లతో మీకు అంతరాయం కలగదు. మీరు ఇప్పటికీ సంగీతం, వీడియోలు మరియు గేమ్లతో సహా మీరు ప్లే చేయడానికి ఎంచుకున్నవి ఏవైనా వింటారు."</string> <string name="zen_priority_customize_button" msgid="4119213187257195047">"అనుకూలంగా మార్చండి"</string> @@ -471,6 +475,8 @@ <string name="keyguard_indication_charging_time_slowly" msgid="301936949731705417">"<xliff:g id="PERCENTAGE">%2$s</xliff:g> • నెమ్మదిగా ఛార్జ్ అవుతోంది • <xliff:g id="CHARGING_TIME_LEFT">%1$s</xliff:g>లో పూర్తి ఛార్జ్"</string> <string name="keyguard_indication_charging_time_dock" msgid="3149328898931741271">"<xliff:g id="PERCENTAGE">%2$s</xliff:g> • ఛార్జ్ అవుతోంది • <xliff:g id="CHARGING_TIME_LEFT">%1$s</xliff:g>లో పూర్తిగా ఛార్జ్ అవుతుంది"</string> <string name="accessibility_action_open_communal_hub" msgid="3081702792413787849">"లాక్ స్క్రీన్లో విడ్జెట్లు"</string> + <!-- no translation found for accessibility_announcement_communal_widget_added (6911593106099328271) --> + <skip /> <string name="communal_tutorial_indicator_text" msgid="4503010353591430123">"కమ్యూనల్ ట్యుటోరియల్ను ప్రారంభించడానికి ఎడమ వైపునకు స్వైప్ చేయండి"</string> <string name="cta_tile_button_to_open_widget_editor" msgid="3871562362382963878">"అనుకూలంగా మార్చండి"</string> <string name="cta_tile_button_to_dismiss" msgid="3377597875997861754">"విస్మరించండి"</string> @@ -499,8 +505,7 @@ <string name="accessibility_action_label_place_widget" msgid="1914197458644168978">"ఎంచుకున్న విడ్జెట్ కోసం ప్లేస్ను ఎంచుకోండి"</string> <string name="communal_widget_picker_title" msgid="1953369090475731663">"లాక్ స్క్రీన్ విడ్జెట్లు"</string> <string name="communal_widget_picker_description" msgid="490515450110487871">"మీ టాబ్లెట్ లాక్ చేసి ఉన్నా, మీ లాక్ స్క్రీన్లో విడ్జెట్లను ఎవరైనా చూడవచ్చు."</string> - <!-- no translation found for accessibility_action_label_unselect_widget (1041811747619468698) --> - <skip /> + <string name="accessibility_action_label_unselect_widget" msgid="1041811747619468698">"విడ్జెట్ ఎంపిక రద్దు చేయండి"</string> <string name="communal_widgets_disclaimer_title" msgid="1150954395585308868">"లాక్ స్క్రీన్ విడ్జెట్లు"</string> <string name="communal_widgets_disclaimer_text" msgid="1423545475160506349">"విడ్జెట్ను ఉపయోగించి యాప్ను తెరవడానికి, ఇది మీరేనని వెరిఫై చేయాల్సి ఉంటుంది. అలాగే, మీ టాబ్లెట్ లాక్ చేసి ఉన్నప్పటికీ, ఎవరైనా వాటిని చూడగలరని గుర్తుంచుకోండి. కొన్ని విడ్జెట్లు మీ లాక్ స్క్రీన్కు తగినవి కాకపోవచ్చు, వాటిని ఇక్కడ జోడించడం సురక్షితం కాకపోవచ్చు."</string> <string name="communal_widgets_disclaimer_button" msgid="4423059765740780753">"అర్థమైంది"</string> @@ -557,10 +562,8 @@ <string name="media_projection_action_text" msgid="3634906766918186440">"ఇప్పుడే ప్రారంభించండి"</string> <string name="empty_shade_text" msgid="8935967157319717412">"నోటిఫికేషన్లు లేవు"</string> <string name="no_unseen_notif_text" msgid="395512586119868682">"కొత్త నోటిఫికేషన్లు ఏవీ లేవు"</string> - <!-- no translation found for adaptive_notification_edu_hun_title (7790738150177329960) --> - <skip /> - <!-- no translation found for adaptive_notification_edu_hun_text (7743367744129536610) --> - <skip /> + <string name="adaptive_notification_edu_hun_title" msgid="7790738150177329960">"నోటిఫికేషన్ కూల్డౌన్ ఆన్ అయింది"</string> + <string name="adaptive_notification_edu_hun_text" msgid="7743367744129536610">"ఒకేసారి పలు నోటిఫికేషన్లు వస్తే, పరికర వాల్యూమ్, అలర్ట్లు ఆటోమేటిక్గా 2 నిమిషాలకు తగ్గించబడతాయి."</string> <string name="go_to_adaptive_notification_settings" msgid="2423690125178298479">"ఆఫ్ చేయండి"</string> <string name="unlock_to_see_notif_text" msgid="7439033907167561227">"పాత నోటిఫికేషన్ల కోసం అన్లాక్ చేయండి"</string> <string name="quick_settings_disclosure_parental_controls" msgid="2114102871438223600">"ఈ పరికరాన్ని మీ తల్లి/తండ్రి మేనేజ్ చేస్తున్నారు"</string> @@ -1226,7 +1229,6 @@ <string name="accessibility_fingerprint_bouncer" msgid="7189102492498735519">"ప్రామాణీకరణ అవసరం. ప్రామాణీకరించడానికి వేలిముద్ర సెన్సార్ను తాకండి."</string> <string name="ongoing_phone_call_content_description" msgid="5332334388483099947">"ఫోన్ కాల్ జరుగుతోంది"</string> <string name="mobile_data_settings_title" msgid="3955246641380064901">"మొబైల్ డేటా"</string> - <string name="preference_summary_default_combination" msgid="8453246369903749670">"<xliff:g id="STATE">%1$s</xliff:g> / <xliff:g id="NETWORKMODE">%2$s</xliff:g>"</string> <string name="mobile_data_connection_active" msgid="944490013299018227">"కనెక్ట్ చేయబడింది"</string> <string name="mobile_data_temp_connection_active" msgid="4590222725908806824">"తాత్కాలికంగా కనెక్ట్ చేయబడింది"</string> <string name="mobile_data_poor_connection" msgid="819617772268371434">"కనెక్షన్ బాగాలేదు"</string> @@ -1380,7 +1382,10 @@ <string name="touchpad_tutorial_done_button" msgid="176168488821755503">"పూర్తయింది"</string> <string name="touchpad_tutorial_gesture_done" msgid="4784438360736821255">"విజయవంతమైంది!"</string> <string name="touchpad_back_gesture_action_title" msgid="7199067250654332735">"వెనుకకు"</string> - <string name="touchpad_back_gesture_guidance" msgid="4222430588599527272">"వెనుకకు వెళ్లడానికి, టచ్ప్యాడ్లో ఎక్కడైనా మూడు వేళ్లను ఉపయోగించి ఎడమ లేదా కుడికి స్వైప్ చేయండి."</string> + <!-- no translation found for touchpad_back_gesture_guidance (6263750214998421587) --> + <skip /> + <!-- no translation found for touchpad_back_gesture_finished (5353616006999726249) --> + <skip /> <string name="touchpad_back_gesture_animation_content_description" msgid="2646107450922379918">"మూడు వేళ్లు కుడి, ఎడమకు కదులుతున్నట్లు చూపే టచ్ప్యాడ్"</string> <string name="touchpad_back_gesture_screen_animation_content_description" msgid="4036267494237748710">"వెనుక సంజ్ఞ కోసం యానిమేషన్ను చూపుతున్న పరికర స్క్రీన్"</string> <string name="keyboard_backlight_dialog_title" msgid="8273102932345564724">"కీబోర్డ్ బ్యాక్లైట్"</string> @@ -1388,28 +1393,16 @@ <string name="home_controls_dream_label" msgid="6567105701292324257">"హోమ్ కంట్రోల్స్"</string> <string name="home_controls_dream_description" msgid="4644150952104035789">"హోమ్ కంట్రోల్స్ను స్క్రీన్ సేవర్గా చేసి వేగంగా యాక్సెస్ పొందండి"</string> <string name="volume_undo_action" msgid="5815519725211877114">"చర్య రద్దు చేయండి"</string> - <!-- no translation found for back_edu_toast_content (4530314597378982956) --> - <skip /> - <!-- no translation found for home_edu_toast_content (3381071147871955415) --> - <skip /> - <!-- no translation found for overview_edu_toast_content (5797030644017804518) --> - <skip /> - <!-- no translation found for all_apps_edu_toast_content (8807496014667211562) --> - <skip /> - <!-- no translation found for back_edu_notification_title (5624780717751357278) --> - <skip /> - <!-- no translation found for back_edu_notification_content (2497557451540954068) --> - <skip /> - <!-- no translation found for home_edu_notification_title (6097902076909654045) --> - <skip /> - <!-- no translation found for home_edu_notification_content (6631697734535766588) --> - <skip /> - <!-- no translation found for overview_edu_notification_title (1265824157319562406) --> - <skip /> - <!-- no translation found for overview_edu_notification_content (3578204677648432500) --> - <skip /> - <!-- no translation found for all_apps_edu_notification_title (372262997265569063) --> - <skip /> - <!-- no translation found for all_apps_edu_notification_content (3255070575694025585) --> - <skip /> + <string name="back_edu_toast_content" msgid="4530314597378982956">"వెనుకకు వెళ్లడానికి, టచ్ప్యాడ్లో మూడు వేళ్లను ఉపయోగించి ఎడమ లేదా కుడి వైపునకు స్వైప్ చేయండి"</string> + <string name="home_edu_toast_content" msgid="3381071147871955415">"హోమ్కు వెళ్లడానికి, టచ్ప్యాడ్లో మీ మూడు వెళ్లతో పైకి స్వైప్ చేయండి"</string> + <string name="overview_edu_toast_content" msgid="5797030644017804518">"ఇటీవలి యాప్లను చూడటానికి, టచ్ప్యాడ్లో మూడు వేళ్లతో పైకి స్వైప్ చేసి, హోల్డ్ చేయండి"</string> + <string name="all_apps_edu_toast_content" msgid="8807496014667211562">"మీ యాప్లన్నింటినీ చూడటానికి, మీ కీబోర్డ్లో యాక్షన్ కీని నొక్కండి"</string> + <string name="back_edu_notification_title" msgid="5624780717751357278">"వెనుకకు వెళ్లడానికి మీ టచ్ప్యాడ్ను ఉపయోగించండి"</string> + <string name="back_edu_notification_content" msgid="2497557451540954068">"మూడు వేళ్లతో ఎడమ / కుడి వైపునకు స్వైప్ చేయండి. మరిన్ని సంజ్ఞల గురించి తెలుసుకోవడానికి ట్యాప్ చేయండి."</string> + <string name="home_edu_notification_title" msgid="6097902076909654045">"హోమ్కు వెళ్లడానికి మీ టచ్ప్యాడ్ను ఉపయోగించండి"</string> + <string name="home_edu_notification_content" msgid="6631697734535766588">"మూడు వేళ్లను ఉపయోగించి పైకి స్వైప్ చేయండి. మరిన్ని సంజ్ఞల గురించి తెలుసుకోవడానికి ట్యాప్ చేయండి."</string> + <string name="overview_edu_notification_title" msgid="1265824157319562406">"ఇటీవలి యాప్లను చూడటానికి మీ టచ్ప్యాడ్ను ఉపయోగించండి"</string> + <string name="overview_edu_notification_content" msgid="3578204677648432500">"మూడు వేళ్లతో పైకి స్వైప్ చేసి, హోల్డ్ చేయండి. మరిన్ని సంజ్ఞల గురించి తెలుసుకోవడానికి ట్యాప్ చేయండి."</string> + <string name="all_apps_edu_notification_title" msgid="372262997265569063">"యాప్లన్నింటినీ చూడటానికి మీ కీబోర్డ్ను ఉపయోగించండి"</string> + <string name="all_apps_edu_notification_content" msgid="3255070575694025585">"ఏ సమయంలోనైనా యాక్షన్ కీని నొక్కండి. మరిన్ని సంజ్ఞల గురించి తెలుసుకోవడానికి ట్యాప్ చేయండి."</string> </resources> diff --git a/packages/SystemUI/res/values-te/tiles_states_strings.xml b/packages/SystemUI/res/values-te/tiles_states_strings.xml index 1f70f859cd6e..6584cdd59282 100644 --- a/packages/SystemUI/res/values-te/tiles_states_strings.xml +++ b/packages/SystemUI/res/values-te/tiles_states_strings.xml @@ -56,11 +56,6 @@ <item msgid="5376619709702103243">"ఆఫ్లో ఉంది"</item> <item msgid="4875147066469902392">"ఆన్లో ఉంది"</item> </string-array> - <string-array name="tile_states_modes"> - <item msgid="7764936419245199023">"అందుబాటులో లేదు"</item> - <item msgid="2004750556637773692">"ఆఫ్లో ఉంది"</item> - <item msgid="8968530753931637871">"ఆన్లో ఉంది"</item> - </string-array> <string-array name="tile_states_flashlight"> <item msgid="3465257127433353857">"అందుబాటులో లేదు"</item> <item msgid="5044688398303285224">"ఆఫ్లో ఉంది"</item> diff --git a/packages/SystemUI/res/values-th/strings.xml b/packages/SystemUI/res/values-th/strings.xml index c4e23340c659..0d131ac7279e 100644 --- a/packages/SystemUI/res/values-th/strings.xml +++ b/packages/SystemUI/res/values-th/strings.xml @@ -126,7 +126,7 @@ <string name="screenrecord_save_text" msgid="3008973099800840163">"แตะเพื่อดู"</string> <string name="screenrecord_save_error" msgid="5862648532560118815">"เกิดข้อผิดพลาดในการบันทึกหน้าจอ"</string> <string name="screenrecord_start_error" msgid="2200660692479682368">"เกิดข้อผิดพลาดขณะเริ่มบันทึกหน้าจอ"</string> - <string name="screenrecord_stop_dialog_title" msgid="8716193661764511095">"หยุดบันทึกใช่ไหม"</string> + <string name="screenrecord_stop_dialog_title" msgid="8716193661764511095">"หยุดบันทึกไหม"</string> <string name="screenrecord_stop_dialog_message" msgid="6262768207331626817">"คุณกำลังบันทึกทั้งหน้าจอ"</string> <string name="screenrecord_stop_dialog_message_specific_app" msgid="5995770227684523244">"คุณกำลังบันทึก <xliff:g id="APP_NAME">%1$s</xliff:g>"</string> <string name="screenrecord_stop_dialog_button" msgid="2883812564938194350">"หยุดบันทึก"</string> @@ -138,7 +138,7 @@ <string name="share_to_app_stop_dialog_message_single_app_generic" msgid="6681016774654578261">"คุณกำลังแชร์แอป"</string> <string name="share_to_app_stop_dialog_button" msgid="6334056916284230217">"หยุดแชร์"</string> <string name="cast_screen_to_other_device_chip_accessibility_label" msgid="4687917476203009885">"กำลังแคสต์หน้าจอ"</string> - <string name="cast_to_other_device_stop_dialog_title" msgid="7836517190930357326">"หยุดการแคสต์ไหม"</string> + <string name="cast_to_other_device_stop_dialog_title" msgid="7836517190930357326">"หยุดแคสต์ไหม"</string> <string name="cast_to_other_device_stop_dialog_message_entire_screen_with_device" msgid="1474703115926205251">"คุณกำลังแคสต์ทั้งหน้าจอไปยัง <xliff:g id="DEVICE_NAME">%1$s</xliff:g>"</string> <string name="cast_to_other_device_stop_dialog_message_entire_screen" msgid="8419219169553867625">"คุณกำลังแคสต์ทั้งหน้าจอไปยังอุปกรณ์ที่อยู่ใกล้เคียง"</string> <string name="cast_to_other_device_stop_dialog_message_specific_app_with_device" msgid="2715934698604085519">"คุณกำลังแคสต์ <xliff:g id="APP_BEING_SHARED_NAME">%1$s</xliff:g> ไปยัง <xliff:g id="DEVICE_NAME">%2$s</xliff:g>"</string> @@ -388,6 +388,9 @@ <string name="performance" msgid="6552785217174378320">"ประสิทธิภาพ"</string> <string name="user_interface" msgid="3712869377953950887">"อินเทอร์เฟซผู้ใช้"</string> <string name="thermal" msgid="6758074791325414831">"ความร้อน"</string> + <string name="custom" msgid="3337456985275158299">"กำหนดเอง"</string> + <string name="custom_trace_settings_dialog_title" msgid="2608570500144830554">"การตั้งค่าการติดตามแบบกำหนดเอง"</string> + <string name="restore_default" msgid="5259420807486239755">"คืนค่าเริ่มต้น"</string> <string name="quick_settings_onehanded_label" msgid="2416537930246274991">"โหมดมือเดียว"</string> <string name="quick_settings_hearing_devices_label" msgid="7277170419679404129">"เครื่องช่วยฟัง"</string> <string name="quick_settings_hearing_devices_connected" msgid="6519069502397037781">"ใช้งานอยู่"</string> @@ -429,9 +432,13 @@ <string name="zen_modes_dialog_title" msgid="4159138230418567383">"โหมดสำคัญ"</string> <string name="zen_modes_dialog_done" msgid="6654130880256438950">"เสร็จสิ้น"</string> <string name="zen_modes_dialog_settings" msgid="2310248023728936697">"การตั้งค่า"</string> - <!-- no translation found for zen_mode_on (9085304934016242591) --> + <string name="zen_mode_on" msgid="9085304934016242591">"เปิด"</string> + <string name="zen_mode_off" msgid="1736604456618147306">"ปิด"</string> + <!-- no translation found for zen_mode_set_up (7457957033034460064) --> <skip /> - <!-- no translation found for zen_mode_off (1736604456618147306) --> + <!-- no translation found for zen_mode_no_manual_invocation (1769975741344633672) --> + <skip /> + <!-- no translation found for zen_mode_active_modes (1625850411578488856) --> <skip /> <string name="zen_priority_introduction" msgid="3159291973383796646">"คุณจะไม่ถูกรบกวนจากเสียงและการสั่น ยกเว้นเสียงนาฬิกาปลุก การช่วยเตือน กิจกรรม และผู้โทรที่ระบุไว้ คุณจะยังคงได้ยินสิ่งที่คุณเลือกเล่น เช่น เพลง วิดีโอ และเกม"</string> <string name="zen_alarms_introduction" msgid="3987266042682300470">"คุณจะไม่ถูกรบกวนจากเสียงและการสั่น ยกเว้นเสียงนาฬิกาปลุก คุณจะยังคงได้ยินสิ่งที่คุณเลือกเล่น เช่น เพลง วิดีโอ และเกม"</string> @@ -471,6 +478,8 @@ <string name="keyguard_indication_charging_time_slowly" msgid="301936949731705417">"<xliff:g id="PERCENTAGE">%2$s</xliff:g> • กำลังชาร์จอย่างช้าๆ • จะเต็มในอีก <xliff:g id="CHARGING_TIME_LEFT">%1$s</xliff:g>"</string> <string name="keyguard_indication_charging_time_dock" msgid="3149328898931741271">"<xliff:g id="PERCENTAGE">%2$s</xliff:g> • กำลังชาร์จ • จะเต็มในอีก <xliff:g id="CHARGING_TIME_LEFT">%1$s</xliff:g>"</string> <string name="accessibility_action_open_communal_hub" msgid="3081702792413787849">"วิดเจ็ตในหน้าจอล็อก"</string> + <!-- no translation found for accessibility_announcement_communal_widget_added (6911593106099328271) --> + <skip /> <string name="communal_tutorial_indicator_text" msgid="4503010353591430123">"ปัดไปทางซ้ายเพื่อเริ่มบทแนะนำส่วนกลาง"</string> <string name="cta_tile_button_to_open_widget_editor" msgid="3871562362382963878">"ปรับแต่ง"</string> <string name="cta_tile_button_to_dismiss" msgid="3377597875997861754">"ปิด"</string> @@ -499,8 +508,7 @@ <string name="accessibility_action_label_place_widget" msgid="1914197458644168978">"จัดวางวิดเจ็ตที่เลือก"</string> <string name="communal_widget_picker_title" msgid="1953369090475731663">"วิดเจ็ตในหน้าจอล็อก"</string> <string name="communal_widget_picker_description" msgid="490515450110487871">"ทุกคนจะดูวิดเจ็ตที่อยู่ในหน้าจอล็อกของคุณได้ แม้ว่าแท็บเล็ตจะล็อกอยู่ก็ตาม"</string> - <!-- no translation found for accessibility_action_label_unselect_widget (1041811747619468698) --> - <skip /> + <string name="accessibility_action_label_unselect_widget" msgid="1041811747619468698">"ยกเลิกการเลือกวิดเจ็ต"</string> <string name="communal_widgets_disclaimer_title" msgid="1150954395585308868">"วิดเจ็ตในหน้าจอล็อก"</string> <string name="communal_widgets_disclaimer_text" msgid="1423545475160506349">"หากต้องการเปิดแอปโดยใช้วิดเจ็ต คุณจะต้องยืนยันตัวตนของคุณ นอกจากนี้ โปรดทราบว่าผู้อื่นจะดูวิดเจ็ตเหล่านี้ได้แม้ว่าแท็บเล็ตจะล็อกอยู่ก็ตาม วิดเจ็ตบางอย่างอาจไม่ได้มีไว้สำหรับหน้าจอล็อกของคุณ และอาจไม่ปลอดภัยที่จะเพิ่มที่นี่"</string> <string name="communal_widgets_disclaimer_button" msgid="4423059765740780753">"รับทราบ"</string> @@ -557,10 +565,8 @@ <string name="media_projection_action_text" msgid="3634906766918186440">"เริ่มเลย"</string> <string name="empty_shade_text" msgid="8935967157319717412">"ไม่มีการแจ้งเตือน"</string> <string name="no_unseen_notif_text" msgid="395512586119868682">"ไม่มีการแจ้งเตือนใหม่"</string> - <!-- no translation found for adaptive_notification_edu_hun_title (7790738150177329960) --> - <skip /> - <!-- no translation found for adaptive_notification_edu_hun_text (7743367744129536610) --> - <skip /> + <string name="adaptive_notification_edu_hun_title" msgid="7790738150177329960">"การพักการแจ้งเตือนเปิดอยู่"</string> + <string name="adaptive_notification_edu_hun_text" msgid="7743367744129536610">"ระบบจะลดระดับเสียงและจำนวนการแจ้งเตือนของอุปกรณ์โดยอัตโนมัติสูงสุด 2 นาทีเมื่อคุณได้รับการแจ้งเตือนพร้อมกันมากเกินไป"</string> <string name="go_to_adaptive_notification_settings" msgid="2423690125178298479">"ปิด"</string> <string name="unlock_to_see_notif_text" msgid="7439033907167561227">"ปลดล็อกเพื่อดูการแจ้งเตือนเก่า"</string> <string name="quick_settings_disclosure_parental_controls" msgid="2114102871438223600">"อุปกรณ์นี้จัดการโดยผู้ปกครอง"</string> @@ -1226,7 +1232,6 @@ <string name="accessibility_fingerprint_bouncer" msgid="7189102492498735519">"ต้องมีการตรวจสอบสิทธิ์ แตะเซ็นเซอร์ลายนิ้วมือเพื่อตรวจสอบสิทธิ์"</string> <string name="ongoing_phone_call_content_description" msgid="5332334388483099947">"กำลังโทรอยู่"</string> <string name="mobile_data_settings_title" msgid="3955246641380064901">"อินเทอร์เน็ตมือถือ"</string> - <string name="preference_summary_default_combination" msgid="8453246369903749670">"<xliff:g id="STATE">%1$s</xliff:g> / <xliff:g id="NETWORKMODE">%2$s</xliff:g>"</string> <string name="mobile_data_connection_active" msgid="944490013299018227">"เชื่อมต่อแล้ว"</string> <string name="mobile_data_temp_connection_active" msgid="4590222725908806824">"เชื่อมต่อแล้วชั่วคราว"</string> <string name="mobile_data_poor_connection" msgid="819617772268371434">"การเชื่อมต่อไม่ดี"</string> @@ -1380,7 +1385,10 @@ <string name="touchpad_tutorial_done_button" msgid="176168488821755503">"เสร็จสิ้น"</string> <string name="touchpad_tutorial_gesture_done" msgid="4784438360736821255">"เก่งมาก"</string> <string name="touchpad_back_gesture_action_title" msgid="7199067250654332735">"ย้อนกลับ"</string> - <string name="touchpad_back_gesture_guidance" msgid="4222430588599527272">"หากต้องการย้อนกลับ ให้ใช้ 3 นิ้วปัดไปทางซ้ายหรือขวาที่ใดก็ได้บนทัชแพด"</string> + <!-- no translation found for touchpad_back_gesture_guidance (6263750214998421587) --> + <skip /> + <!-- no translation found for touchpad_back_gesture_finished (5353616006999726249) --> + <skip /> <string name="touchpad_back_gesture_animation_content_description" msgid="2646107450922379918">"ทัชแพดแสดงภาพ 3 นิ้วเลื่อนไปทางขวาและซ้าย"</string> <string name="touchpad_back_gesture_screen_animation_content_description" msgid="4036267494237748710">"หน้าจออุปกรณ์แสดงภาพเคลื่อนไหวของท่าทางสัมผัสย้อนกลับ"</string> <string name="keyboard_backlight_dialog_title" msgid="8273102932345564724">"ไฟแบ็กไลต์ของแป้นพิมพ์"</string> @@ -1388,28 +1396,16 @@ <string name="home_controls_dream_label" msgid="6567105701292324257">"ระบบควบคุมอุปกรณ์สมาร์ทโฮม"</string> <string name="home_controls_dream_description" msgid="4644150952104035789">"เข้าถึงระบบควบคุมอุปกรณ์สมาร์ทโฮมได้อย่างรวดเร็วผ่านภาพพักหน้าจอ"</string> <string name="volume_undo_action" msgid="5815519725211877114">"เลิกทำ"</string> - <!-- no translation found for back_edu_toast_content (4530314597378982956) --> - <skip /> - <!-- no translation found for home_edu_toast_content (3381071147871955415) --> - <skip /> - <!-- no translation found for overview_edu_toast_content (5797030644017804518) --> - <skip /> - <!-- no translation found for all_apps_edu_toast_content (8807496014667211562) --> - <skip /> - <!-- no translation found for back_edu_notification_title (5624780717751357278) --> - <skip /> - <!-- no translation found for back_edu_notification_content (2497557451540954068) --> - <skip /> - <!-- no translation found for home_edu_notification_title (6097902076909654045) --> - <skip /> - <!-- no translation found for home_edu_notification_content (6631697734535766588) --> - <skip /> - <!-- no translation found for overview_edu_notification_title (1265824157319562406) --> - <skip /> - <!-- no translation found for overview_edu_notification_content (3578204677648432500) --> - <skip /> - <!-- no translation found for all_apps_edu_notification_title (372262997265569063) --> - <skip /> - <!-- no translation found for all_apps_edu_notification_content (3255070575694025585) --> - <skip /> + <string name="back_edu_toast_content" msgid="4530314597378982956">"หากต้องการย้อนกลับ ให้ใช้ 3 นิ้วปัดไปทางซ้ายหรือขวาบนทัชแพด"</string> + <string name="home_edu_toast_content" msgid="3381071147871955415">"หากต้องการไปที่หน้าแรก ให้ใช้ 3 นิ้วปัดขึ้นบนทัชแพด"</string> + <string name="overview_edu_toast_content" msgid="5797030644017804518">"หากต้องการดูแอปล่าสุด ให้ใช้ 3 นิ้วปัดขึ้นแล้วค้างไว้บนทัชแพด"</string> + <string name="all_apps_edu_toast_content" msgid="8807496014667211562">"หากต้องการดูแอปทั้งหมด ให้กดปุ่มดำเนินการบนแป้นพิมพ์"</string> + <string name="back_edu_notification_title" msgid="5624780717751357278">"ใช้ทัชแพดเพื่อย้อนกลับ"</string> + <string name="back_edu_notification_content" msgid="2497557451540954068">"ใช้ 3 นิ้วปัดไปทางซ้ายหรือขวา แตะเพื่อดูข้อมูลเพิ่มเติมเกี่ยวกับท่าทางสัมผัสต่างๆ"</string> + <string name="home_edu_notification_title" msgid="6097902076909654045">"ใช้ทัชแพดเพื่อไปยังหน้าแรก"</string> + <string name="home_edu_notification_content" msgid="6631697734535766588">"ใช้ 3 นิ้วปัดขึ้น แตะเพื่อดูข้อมูลเพิ่มเติมเกี่ยวกับท่าทางสัมผัสต่างๆ"</string> + <string name="overview_edu_notification_title" msgid="1265824157319562406">"ใช้ทัชแพดเพื่อดูแอปล่าสุด"</string> + <string name="overview_edu_notification_content" msgid="3578204677648432500">"ใช้ 3 นิ้วปัดขึ้นแล้วค้างไว้ แตะเพื่อดูข้อมูลเพิ่มเติมเกี่ยวกับท่าทางสัมผัสต่างๆ"</string> + <string name="all_apps_edu_notification_title" msgid="372262997265569063">"ใช้แป้นพิมพ์เพื่อดูแอปทั้งหมด"</string> + <string name="all_apps_edu_notification_content" msgid="3255070575694025585">"กดปุ่มดำเนินการได้ทุกเมื่อ แตะเพื่อดูข้อมูลเพิ่มเติมเกี่ยวกับท่าทางสัมผัสต่างๆ"</string> </resources> diff --git a/packages/SystemUI/res/values-th/tiles_states_strings.xml b/packages/SystemUI/res/values-th/tiles_states_strings.xml index 20f66da1bfe0..8b7187b66baa 100644 --- a/packages/SystemUI/res/values-th/tiles_states_strings.xml +++ b/packages/SystemUI/res/values-th/tiles_states_strings.xml @@ -56,11 +56,6 @@ <item msgid="5376619709702103243">"ปิด"</item> <item msgid="4875147066469902392">"เปิด"</item> </string-array> - <string-array name="tile_states_modes"> - <item msgid="7764936419245199023">"ไม่พร้อมใช้งาน"</item> - <item msgid="2004750556637773692">"ปิด"</item> - <item msgid="8968530753931637871">"เปิด"</item> - </string-array> <string-array name="tile_states_flashlight"> <item msgid="3465257127433353857">"ไม่พร้อมใช้งาน"</item> <item msgid="5044688398303285224">"ปิด"</item> diff --git a/packages/SystemUI/res/values-tl/strings.xml b/packages/SystemUI/res/values-tl/strings.xml index a00bcc03524b..f836acacbf25 100644 --- a/packages/SystemUI/res/values-tl/strings.xml +++ b/packages/SystemUI/res/values-tl/strings.xml @@ -388,6 +388,9 @@ <string name="performance" msgid="6552785217174378320">"Performance"</string> <string name="user_interface" msgid="3712869377953950887">"User Interface"</string> <string name="thermal" msgid="6758074791325414831">"Thermal"</string> + <string name="custom" msgid="3337456985275158299">"Custom"</string> + <string name="custom_trace_settings_dialog_title" msgid="2608570500144830554">"Mga Setting ng Custom na Trace"</string> + <string name="restore_default" msgid="5259420807486239755">"I-restore ang Default"</string> <string name="quick_settings_onehanded_label" msgid="2416537930246274991">"One-hand mode"</string> <string name="quick_settings_hearing_devices_label" msgid="7277170419679404129">"Mga hearing device"</string> <string name="quick_settings_hearing_devices_connected" msgid="6519069502397037781">"Aktibo"</string> @@ -429,9 +432,13 @@ <string name="zen_modes_dialog_title" msgid="4159138230418567383">"Mga priyoridad na mode"</string> <string name="zen_modes_dialog_done" msgid="6654130880256438950">"Tapos na"</string> <string name="zen_modes_dialog_settings" msgid="2310248023728936697">"Mga Setting"</string> - <!-- no translation found for zen_mode_on (9085304934016242591) --> + <string name="zen_mode_on" msgid="9085304934016242591">"Naka-on"</string> + <string name="zen_mode_off" msgid="1736604456618147306">"Naka-off"</string> + <!-- no translation found for zen_mode_set_up (7457957033034460064) --> <skip /> - <!-- no translation found for zen_mode_off (1736604456618147306) --> + <!-- no translation found for zen_mode_no_manual_invocation (1769975741344633672) --> + <skip /> + <!-- no translation found for zen_mode_active_modes (1625850411578488856) --> <skip /> <string name="zen_priority_introduction" msgid="3159291973383796646">"Hindi ka maiistorbo ng mga tunog at pag-vibrate, maliban mula sa mga alarm, paalala, event, at tumatawag na tutukuyin mo. Maririnig mo pa rin ang kahit na anong piliin mong i-play kabilang ang mga musika, video, at laro."</string> <string name="zen_alarms_introduction" msgid="3987266042682300470">"Hindi ka maiistorbo ng mga tunog at pag-vibrate, maliban sa mga alarm. Maririnig mo pa rin ang anumang pipiliin mong i-play kabilang ang mga musika, video, at laro."</string> @@ -471,6 +478,8 @@ <string name="keyguard_indication_charging_time_slowly" msgid="301936949731705417">"<xliff:g id="PERCENTAGE">%2$s</xliff:g> • Mabagal na nagcha-charge • <xliff:g id="CHARGING_TIME_LEFT">%1$s</xliff:g> na lang para mapuno"</string> <string name="keyguard_indication_charging_time_dock" msgid="3149328898931741271">"<xliff:g id="PERCENTAGE">%2$s</xliff:g> • Nagcha-charge • <xliff:g id="CHARGING_TIME_LEFT">%1$s</xliff:g> na lang para mapuno"</string> <string name="accessibility_action_open_communal_hub" msgid="3081702792413787849">"Mga widget sa lock screen"</string> + <!-- no translation found for accessibility_announcement_communal_widget_added (6911593106099328271) --> + <skip /> <string name="communal_tutorial_indicator_text" msgid="4503010353591430123">"Mag-swipe pakaliwa para simulan ang communal na tutorial"</string> <string name="cta_tile_button_to_open_widget_editor" msgid="3871562362382963878">"I-customize"</string> <string name="cta_tile_button_to_dismiss" msgid="3377597875997861754">"I-dismiss"</string> @@ -499,8 +508,7 @@ <string name="accessibility_action_label_place_widget" msgid="1914197458644168978">"ilagay ang napiling widget"</string> <string name="communal_widget_picker_title" msgid="1953369090475731663">"Mga widget ng lock screen"</string> <string name="communal_widget_picker_description" msgid="490515450110487871">"Makikita ng sinuman ang mga widget sa lock screen, kahit naka-lock ang tablet."</string> - <!-- no translation found for accessibility_action_label_unselect_widget (1041811747619468698) --> - <skip /> + <string name="accessibility_action_label_unselect_widget" msgid="1041811747619468698">"i-unselect ang widget"</string> <string name="communal_widgets_disclaimer_title" msgid="1150954395585308868">"Mga widget ng lock screen"</string> <string name="communal_widgets_disclaimer_text" msgid="1423545475160506349">"Para magbukas ng app gamit ang isang widget, kakailanganin mong i-verify na ikaw iyan. Bukod pa rito, tandaang puwedeng tingnan ng kahit na sino ang mga ito, kahit na naka-lock ang iyong tablet. Posibleng hindi para sa iyong lock screen ang ilang widget at posibleng hindi ligtas ang mga ito na idagdag dito."</string> <string name="communal_widgets_disclaimer_button" msgid="4423059765740780753">"OK"</string> @@ -557,10 +565,8 @@ <string name="media_projection_action_text" msgid="3634906766918186440">"Magsimula ngayon"</string> <string name="empty_shade_text" msgid="8935967157319717412">"Walang mga notification"</string> <string name="no_unseen_notif_text" msgid="395512586119868682">"Walang bagong notification"</string> - <!-- no translation found for adaptive_notification_edu_hun_title (7790738150177329960) --> - <skip /> - <!-- no translation found for adaptive_notification_edu_hun_text (7743367744129536610) --> - <skip /> + <string name="adaptive_notification_edu_hun_title" msgid="7790738150177329960">"Naka-on ang cooldown sa notification"</string> + <string name="adaptive_notification_edu_hun_text" msgid="7743367744129536610">"Babawasan ang volume at alerto nang hanggang 2 minuto kapag nakatanggap ng maraming notification."</string> <string name="go_to_adaptive_notification_settings" msgid="2423690125178298479">"I-off"</string> <string name="unlock_to_see_notif_text" msgid="7439033907167561227">"I-unlock para makita ang mga mas lumang notification"</string> <string name="quick_settings_disclosure_parental_controls" msgid="2114102871438223600">"Pinapamahalaan ng magulang mo itong device"</string> @@ -1226,7 +1232,6 @@ <string name="accessibility_fingerprint_bouncer" msgid="7189102492498735519">"Kailangan ng pag-authenticate. Pindutin ang sensor para sa fingerprint para mag-authenticate."</string> <string name="ongoing_phone_call_content_description" msgid="5332334388483099947">"Kasalukuyang may tawag sa telepono"</string> <string name="mobile_data_settings_title" msgid="3955246641380064901">"Mobile data"</string> - <string name="preference_summary_default_combination" msgid="8453246369903749670">"<xliff:g id="STATE">%1$s</xliff:g> / <xliff:g id="NETWORKMODE">%2$s</xliff:g>"</string> <string name="mobile_data_connection_active" msgid="944490013299018227">"Nakakonekta"</string> <string name="mobile_data_temp_connection_active" msgid="4590222725908806824">"Pansamantalang nakakonekta"</string> <string name="mobile_data_poor_connection" msgid="819617772268371434">"Mahina ang koneksyon"</string> @@ -1380,7 +1385,10 @@ <string name="touchpad_tutorial_done_button" msgid="176168488821755503">"Tapos na"</string> <string name="touchpad_tutorial_gesture_done" msgid="4784438360736821255">"Magaling!"</string> <string name="touchpad_back_gesture_action_title" msgid="7199067250654332735">"Bumalik"</string> - <string name="touchpad_back_gesture_guidance" msgid="4222430588599527272">"Para bumalik, mag-swipe pakaliwa o pakanan gamit ang tatlong daliri kahit saan sa touchpad."</string> + <!-- no translation found for touchpad_back_gesture_guidance (6263750214998421587) --> + <skip /> + <!-- no translation found for touchpad_back_gesture_finished (5353616006999726249) --> + <skip /> <string name="touchpad_back_gesture_animation_content_description" msgid="2646107450922379918">"Touchpad na nagpapakita ng tatlong daliring gumagalaw pakanan at pakaliwa"</string> <string name="touchpad_back_gesture_screen_animation_content_description" msgid="4036267494237748710">"Screen ng device na nagpapakita ng animation para sa galaw sa pagbalik"</string> <string name="keyboard_backlight_dialog_title" msgid="8273102932345564724">"Backlight ng keyboard"</string> @@ -1388,28 +1396,16 @@ <string name="home_controls_dream_label" msgid="6567105701292324257">"Mga Home Control"</string> <string name="home_controls_dream_description" msgid="4644150952104035789">"Mabilis i-access ang home control bilang screensaver"</string> <string name="volume_undo_action" msgid="5815519725211877114">"I-undo"</string> - <!-- no translation found for back_edu_toast_content (4530314597378982956) --> - <skip /> - <!-- no translation found for home_edu_toast_content (3381071147871955415) --> - <skip /> - <!-- no translation found for overview_edu_toast_content (5797030644017804518) --> - <skip /> - <!-- no translation found for all_apps_edu_toast_content (8807496014667211562) --> - <skip /> - <!-- no translation found for back_edu_notification_title (5624780717751357278) --> - <skip /> - <!-- no translation found for back_edu_notification_content (2497557451540954068) --> - <skip /> - <!-- no translation found for home_edu_notification_title (6097902076909654045) --> - <skip /> - <!-- no translation found for home_edu_notification_content (6631697734535766588) --> - <skip /> - <!-- no translation found for overview_edu_notification_title (1265824157319562406) --> - <skip /> - <!-- no translation found for overview_edu_notification_content (3578204677648432500) --> - <skip /> - <!-- no translation found for all_apps_edu_notification_title (372262997265569063) --> - <skip /> - <!-- no translation found for all_apps_edu_notification_content (3255070575694025585) --> - <skip /> + <string name="back_edu_toast_content" msgid="4530314597378982956">"Para bumalik, mag-swipe pakaliwa o pakanan gamit ang tatlong daliri sa touchpad."</string> + <string name="home_edu_toast_content" msgid="3381071147871955415">"Para pumunta sa home, mag-swipe pataas gamit ang tatlong daliri sa touchpad"</string> + <string name="overview_edu_toast_content" msgid="5797030644017804518">"Para tingnan ang kamakailang app, mag-swipe pataas at i-hold gamit ang tatlong daliri sa touchpad"</string> + <string name="all_apps_edu_toast_content" msgid="8807496014667211562">"Para tingnan ang lahat ng iyong app, pindutin ang action key sa keyboard mo"</string> + <string name="back_edu_notification_title" msgid="5624780717751357278">"Gamitin ang iyong touchpad para bumalik"</string> + <string name="back_edu_notification_content" msgid="2497557451540954068">"Mag-swipe pakaliwa o pakanan gamit ang tatlong daliri. I-tap para matuto pa tungkol sa mga galaw."</string> + <string name="home_edu_notification_title" msgid="6097902076909654045">"Gamitin ang touchpad mo para pumunta sa home"</string> + <string name="home_edu_notification_content" msgid="6631697734535766588">"Mag-swipe pataas gamit ang tatlong daliri I-tap para matuto pa tungkol sa mga galaw."</string> + <string name="overview_edu_notification_title" msgid="1265824157319562406">"Gamitin ang iyong touchpad para tingnan ang mga kamakailang app"</string> + <string name="overview_edu_notification_content" msgid="3578204677648432500">"Mag-swipe pataas at i-hold gamit ang tatlong daliri. I-tap para matuto pa tungkol sa mga galaw."</string> + <string name="all_apps_edu_notification_title" msgid="372262997265569063">"Gamitin ang iyong keyboard para tingnan ang lahat ng app"</string> + <string name="all_apps_edu_notification_content" msgid="3255070575694025585">"Pindutin ang action key kahit kailan. I-tap para matuto pa tungkol sa mga galaw."</string> </resources> diff --git a/packages/SystemUI/res/values-tl/tiles_states_strings.xml b/packages/SystemUI/res/values-tl/tiles_states_strings.xml index 85c4cfab149c..fe2827f6a4e9 100644 --- a/packages/SystemUI/res/values-tl/tiles_states_strings.xml +++ b/packages/SystemUI/res/values-tl/tiles_states_strings.xml @@ -56,11 +56,6 @@ <item msgid="5376619709702103243">"Naka-off"</item> <item msgid="4875147066469902392">"Naka-on"</item> </string-array> - <string-array name="tile_states_modes"> - <item msgid="7764936419245199023">"Hindi available"</item> - <item msgid="2004750556637773692">"Naka-off"</item> - <item msgid="8968530753931637871">"Naka-on"</item> - </string-array> <string-array name="tile_states_flashlight"> <item msgid="3465257127433353857">"Hindi available"</item> <item msgid="5044688398303285224">"Naka-off"</item> diff --git a/packages/SystemUI/res/values-tr/strings.xml b/packages/SystemUI/res/values-tr/strings.xml index 855febef18f7..b30df3d0426c 100644 --- a/packages/SystemUI/res/values-tr/strings.xml +++ b/packages/SystemUI/res/values-tr/strings.xml @@ -388,6 +388,9 @@ <string name="performance" msgid="6552785217174378320">"Performans"</string> <string name="user_interface" msgid="3712869377953950887">"Kullanıcı Arayüzü"</string> <string name="thermal" msgid="6758074791325414831">"Termal"</string> + <string name="custom" msgid="3337456985275158299">"Özel"</string> + <string name="custom_trace_settings_dialog_title" msgid="2608570500144830554">"Özel İz Ayarları"</string> + <string name="restore_default" msgid="5259420807486239755">"Varsayılanları Geri Yükle"</string> <string name="quick_settings_onehanded_label" msgid="2416537930246274991">"Tek el modu"</string> <string name="quick_settings_hearing_devices_label" msgid="7277170419679404129">"İşitme cihazları"</string> <string name="quick_settings_hearing_devices_connected" msgid="6519069502397037781">"Etkin"</string> @@ -429,9 +432,13 @@ <string name="zen_modes_dialog_title" msgid="4159138230418567383">"Öncelik modları"</string> <string name="zen_modes_dialog_done" msgid="6654130880256438950">"Bitti"</string> <string name="zen_modes_dialog_settings" msgid="2310248023728936697">"Ayarlar"</string> - <!-- no translation found for zen_mode_on (9085304934016242591) --> + <string name="zen_mode_on" msgid="9085304934016242591">"Açık"</string> + <string name="zen_mode_off" msgid="1736604456618147306">"Kapalı"</string> + <!-- no translation found for zen_mode_set_up (7457957033034460064) --> <skip /> - <!-- no translation found for zen_mode_off (1736604456618147306) --> + <!-- no translation found for zen_mode_no_manual_invocation (1769975741344633672) --> + <skip /> + <!-- no translation found for zen_mode_active_modes (1625850411578488856) --> <skip /> <string name="zen_priority_introduction" msgid="3159291973383796646">"Alarmlar, hatırlatıcılar, etkinlikler ve sizin seçtiğiniz kişilerden gelen çağrılar dışında hiçbir ses ve titreşimle rahatsız edilmeyeceksiniz. O sırada çaldığınız müzik, seyrettiğiniz video ya da oynadığınız oyunların sesini duymaya devam edeceksiniz."</string> <string name="zen_alarms_introduction" msgid="3987266042682300470">"Alarmlar dışında hiçbir ses ve titreşimle rahatsız edilmeyeceksiniz. O sırada çaldığınız müzik, seyrettiğiniz video ya da oynadığınız oyunların sesini duymaya devam edeceksiniz."</string> @@ -471,6 +478,8 @@ <string name="keyguard_indication_charging_time_slowly" msgid="301936949731705417">"<xliff:g id="PERCENTAGE">%2$s</xliff:g> • Yavaş şarj oluyor • Dolmasına <xliff:g id="CHARGING_TIME_LEFT">%1$s</xliff:g> kaldı"</string> <string name="keyguard_indication_charging_time_dock" msgid="3149328898931741271">"<xliff:g id="PERCENTAGE">%2$s</xliff:g> • Şarj oluyor • Dolmasına <xliff:g id="CHARGING_TIME_LEFT">%1$s</xliff:g> kaldı"</string> <string name="accessibility_action_open_communal_hub" msgid="3081702792413787849">"Kilit ekranındaki widget\'lar"</string> + <!-- no translation found for accessibility_announcement_communal_widget_added (6911593106099328271) --> + <skip /> <string name="communal_tutorial_indicator_text" msgid="4503010353591430123">"Ortak eğitimi başlatmak için sola kaydırın"</string> <string name="cta_tile_button_to_open_widget_editor" msgid="3871562362382963878">"Özelleştir"</string> <string name="cta_tile_button_to_dismiss" msgid="3377597875997861754">"Kapat"</string> @@ -499,8 +508,7 @@ <string name="accessibility_action_label_place_widget" msgid="1914197458644168978">"seçilen widget\'ı yerleştir"</string> <string name="communal_widget_picker_title" msgid="1953369090475731663">"Kilit ekranı widget\'ları"</string> <string name="communal_widget_picker_description" msgid="490515450110487871">"Kilit ekranınızdaki widget\'lar, tabletiniz kilitliyken bile herkes tarafından görüntülenebilir."</string> - <!-- no translation found for accessibility_action_label_unselect_widget (1041811747619468698) --> - <skip /> + <string name="accessibility_action_label_unselect_widget" msgid="1041811747619468698">"widget\'ın seçimini kaldırın"</string> <string name="communal_widgets_disclaimer_title" msgid="1150954395585308868">"Kilit ekranı widget\'ları"</string> <string name="communal_widgets_disclaimer_text" msgid="1423545475160506349">"Widget kullanarak bir uygulamayı açmak için kimliğinizi doğrulamanız gerekir. Ayrıca, tabletiniz kilitliyken bile widget\'ların herkes tarafından görüntülenebileceğini unutmayın. Bazı widget\'lar kilit ekranınız için tasarlanmamış olabileceğinden buraya eklenmeleri güvenli olmayabilir."</string> <string name="communal_widgets_disclaimer_button" msgid="4423059765740780753">"Anladım"</string> @@ -557,10 +565,8 @@ <string name="media_projection_action_text" msgid="3634906766918186440">"Şimdi başlat"</string> <string name="empty_shade_text" msgid="8935967157319717412">"Bildirim yok"</string> <string name="no_unseen_notif_text" msgid="395512586119868682">"Yeni bildirim yok"</string> - <!-- no translation found for adaptive_notification_edu_hun_title (7790738150177329960) --> - <skip /> - <!-- no translation found for adaptive_notification_edu_hun_text (7743367744129536610) --> - <skip /> + <string name="adaptive_notification_edu_hun_title" msgid="7790738150177329960">"Bildirim şiddetini düşürme etkin"</string> + <string name="adaptive_notification_edu_hun_text" msgid="7743367744129536610">"Aynı anda çok sayıda bildirim aldığınızda 2 dakika boyunca otomatik olarak cihazınızın sesi kısılır ve uyarıları azaltılır."</string> <string name="go_to_adaptive_notification_settings" msgid="2423690125178298479">"Kapat"</string> <string name="unlock_to_see_notif_text" msgid="7439033907167561227">"Eski bildirimler için kilidi açın"</string> <string name="quick_settings_disclosure_parental_controls" msgid="2114102871438223600">"Bu cihaz ebeveyniniz tarafından yönetiliyor"</string> @@ -1226,7 +1232,6 @@ <string name="accessibility_fingerprint_bouncer" msgid="7189102492498735519">"Kimlik doğrulaması gerekiyor. Kimlik doğrulaması için parmak izi sensörüne dokunun."</string> <string name="ongoing_phone_call_content_description" msgid="5332334388483099947">"Devam eden telefon görüşmesi"</string> <string name="mobile_data_settings_title" msgid="3955246641380064901">"Mobil veri"</string> - <string name="preference_summary_default_combination" msgid="8453246369903749670">"<xliff:g id="STATE">%1$s</xliff:g> / <xliff:g id="NETWORKMODE">%2$s</xliff:g>"</string> <string name="mobile_data_connection_active" msgid="944490013299018227">"Bağlı"</string> <string name="mobile_data_temp_connection_active" msgid="4590222725908806824">"Geçici olarak bağlandı"</string> <string name="mobile_data_poor_connection" msgid="819617772268371434">"Bağlantı zayıf"</string> @@ -1380,7 +1385,10 @@ <string name="touchpad_tutorial_done_button" msgid="176168488821755503">"Bitti"</string> <string name="touchpad_tutorial_gesture_done" msgid="4784438360736821255">"Tebrikler!"</string> <string name="touchpad_back_gesture_action_title" msgid="7199067250654332735">"Geri dön"</string> - <string name="touchpad_back_gesture_guidance" msgid="4222430588599527272">"Geri dönmek için dokunmatik alanın herhangi bir yerinde üç parmağınızla sola veya sağa kaydırın."</string> + <!-- no translation found for touchpad_back_gesture_guidance (6263750214998421587) --> + <skip /> + <!-- no translation found for touchpad_back_gesture_finished (5353616006999726249) --> + <skip /> <string name="touchpad_back_gesture_animation_content_description" msgid="2646107450922379918">"Sağa ve sola hareket eden üç parmağın gösterildiği dokunmatik alan"</string> <string name="touchpad_back_gesture_screen_animation_content_description" msgid="4036267494237748710">"Geri hareketi animasyonunu gösteren cihaz ekranı"</string> <string name="keyboard_backlight_dialog_title" msgid="8273102932345564724">"Klavye aydınlatması"</string> @@ -1388,28 +1396,16 @@ <string name="home_controls_dream_label" msgid="6567105701292324257">"Ev Kontrolleri"</string> <string name="home_controls_dream_description" msgid="4644150952104035789">"Ekran koruyucu olarak ev kontrollerinize hızla erişin"</string> <string name="volume_undo_action" msgid="5815519725211877114">"Geri al"</string> - <!-- no translation found for back_edu_toast_content (4530314597378982956) --> - <skip /> - <!-- no translation found for home_edu_toast_content (3381071147871955415) --> - <skip /> - <!-- no translation found for overview_edu_toast_content (5797030644017804518) --> - <skip /> - <!-- no translation found for all_apps_edu_toast_content (8807496014667211562) --> - <skip /> - <!-- no translation found for back_edu_notification_title (5624780717751357278) --> - <skip /> - <!-- no translation found for back_edu_notification_content (2497557451540954068) --> - <skip /> - <!-- no translation found for home_edu_notification_title (6097902076909654045) --> - <skip /> - <!-- no translation found for home_edu_notification_content (6631697734535766588) --> - <skip /> - <!-- no translation found for overview_edu_notification_title (1265824157319562406) --> - <skip /> - <!-- no translation found for overview_edu_notification_content (3578204677648432500) --> - <skip /> - <!-- no translation found for all_apps_edu_notification_title (372262997265569063) --> - <skip /> - <!-- no translation found for all_apps_edu_notification_content (3255070575694025585) --> - <skip /> + <string name="back_edu_toast_content" msgid="4530314597378982956">"Geri dönmek için dokunmatik alanda üç parmağınızla sola veya sağa kaydırın"</string> + <string name="home_edu_toast_content" msgid="3381071147871955415">"Ana sayfaya gitmek için dokunmatik alanda üç parmağınızla yukarı kaydırın"</string> + <string name="overview_edu_toast_content" msgid="5797030644017804518">"Son uygulamaları görüntülemek için dokunmatik alanda üç parmağınızla yukarı kaydırıp basılı tutun"</string> + <string name="all_apps_edu_toast_content" msgid="8807496014667211562">"Tüm uygulamalarınızı görüntülemek için klavyenizdeki eylem tuşuna basın"</string> + <string name="back_edu_notification_title" msgid="5624780717751357278">"Geri dönmek için dokunmatik alanınızı kullanın"</string> + <string name="back_edu_notification_content" msgid="2497557451540954068">"Üç parmağınızla sola veya sağa kaydırın. Daha fazla hareket öğrenmek için dokunun."</string> + <string name="home_edu_notification_title" msgid="6097902076909654045">"Ana sayfaya gitmek için dokunmatik alanınızı kullanın"</string> + <string name="home_edu_notification_content" msgid="6631697734535766588">"Üç parmağınızla yukarı kaydırın. Daha fazla hareket öğrenmek için dokunun."</string> + <string name="overview_edu_notification_title" msgid="1265824157319562406">"Son uygulamaları görüntülemek için dokunmatik alanınızı kullanın"</string> + <string name="overview_edu_notification_content" msgid="3578204677648432500">"Üç parmağınızla yukarı kaydırıp basılı tutun. Daha fazla hareket öğrenmek için dokunun."</string> + <string name="all_apps_edu_notification_title" msgid="372262997265569063">"Tüm uygulamaları görüntülemek için klavyenizi kullanın"</string> + <string name="all_apps_edu_notification_content" msgid="3255070575694025585">"İstediğiniz zaman eylem tuşuna basın. Daha fazla hareket öğrenmek için dokunun."</string> </resources> diff --git a/packages/SystemUI/res/values-tr/tiles_states_strings.xml b/packages/SystemUI/res/values-tr/tiles_states_strings.xml index 1c9224b0141d..1ed106f4efd2 100644 --- a/packages/SystemUI/res/values-tr/tiles_states_strings.xml +++ b/packages/SystemUI/res/values-tr/tiles_states_strings.xml @@ -56,11 +56,6 @@ <item msgid="5376619709702103243">"Kapalı"</item> <item msgid="4875147066469902392">"Açık"</item> </string-array> - <string-array name="tile_states_modes"> - <item msgid="7764936419245199023">"Yok"</item> - <item msgid="2004750556637773692">"Kapalı"</item> - <item msgid="8968530753931637871">"Açık"</item> - </string-array> <string-array name="tile_states_flashlight"> <item msgid="3465257127433353857">"Kullanılamıyor"</item> <item msgid="5044688398303285224">"Kapalı"</item> diff --git a/packages/SystemUI/res/values-uk/strings.xml b/packages/SystemUI/res/values-uk/strings.xml index dec917b11415..7e72f7eb16a5 100644 --- a/packages/SystemUI/res/values-uk/strings.xml +++ b/packages/SystemUI/res/values-uk/strings.xml @@ -388,6 +388,9 @@ <string name="performance" msgid="6552785217174378320">"Продуктивність"</string> <string name="user_interface" msgid="3712869377953950887">"Інтерфейс користувача"</string> <string name="thermal" msgid="6758074791325414831">"Нагрівання"</string> + <string name="custom" msgid="3337456985275158299">"Власні"</string> + <string name="custom_trace_settings_dialog_title" msgid="2608570500144830554">"Власні налаштування трасування"</string> + <string name="restore_default" msgid="5259420807486239755">"Відновити налаштування за умовчанням"</string> <string name="quick_settings_onehanded_label" msgid="2416537930246274991">"Режим керування однією рукою"</string> <string name="quick_settings_hearing_devices_label" msgid="7277170419679404129">"Слухові апарати"</string> <string name="quick_settings_hearing_devices_connected" msgid="6519069502397037781">"Під’єднано"</string> @@ -429,9 +432,13 @@ <string name="zen_modes_dialog_title" msgid="4159138230418567383">"Режими пріоритету"</string> <string name="zen_modes_dialog_done" msgid="6654130880256438950">"Готово"</string> <string name="zen_modes_dialog_settings" msgid="2310248023728936697">"Налаштування"</string> - <!-- no translation found for zen_mode_on (9085304934016242591) --> + <string name="zen_mode_on" msgid="9085304934016242591">"Увімкнено"</string> + <string name="zen_mode_off" msgid="1736604456618147306">"Вимкнено"</string> + <!-- no translation found for zen_mode_set_up (7457957033034460064) --> <skip /> - <!-- no translation found for zen_mode_off (1736604456618147306) --> + <!-- no translation found for zen_mode_no_manual_invocation (1769975741344633672) --> + <skip /> + <!-- no translation found for zen_mode_active_modes (1625850411578488856) --> <skip /> <string name="zen_priority_introduction" msgid="3159291973383796646">"Ви отримуватиме звукові та вібросигнали лише для вибраних будильників, нагадувань, подій і абонентів. Однак ви чутимете все, що захочете відтворити, зокрема музику, відео й ігри."</string> <string name="zen_alarms_introduction" msgid="3987266042682300470">"Ви отримуватиме звукові та вібросигнали лише для будильників. Однак ви чутимете все, що захочете відтворити, зокрема музику, відео й ігри."</string> @@ -471,6 +478,8 @@ <string name="keyguard_indication_charging_time_slowly" msgid="301936949731705417">"<xliff:g id="PERCENTAGE">%2$s</xliff:g> • Повільне заряджання • <xliff:g id="CHARGING_TIME_LEFT">%1$s</xliff:g> до повного заряду"</string> <string name="keyguard_indication_charging_time_dock" msgid="3149328898931741271">"<xliff:g id="PERCENTAGE">%2$s</xliff:g> • Заряджання • <xliff:g id="CHARGING_TIME_LEFT">%1$s</xliff:g> до повного заряду"</string> <string name="accessibility_action_open_communal_hub" msgid="3081702792413787849">"Віджети на заблокованому екрані"</string> + <!-- no translation found for accessibility_announcement_communal_widget_added (6911593106099328271) --> + <skip /> <string name="communal_tutorial_indicator_text" msgid="4503010353591430123">"Проведіть пальцем уліво, щоб відкрити спільний навчальний посібник"</string> <string name="cta_tile_button_to_open_widget_editor" msgid="3871562362382963878">"Налаштувати"</string> <string name="cta_tile_button_to_dismiss" msgid="3377597875997861754">"Закрити"</string> @@ -499,8 +508,7 @@ <string name="accessibility_action_label_place_widget" msgid="1914197458644168978">"розмістити вибраний віджет"</string> <string name="communal_widget_picker_title" msgid="1953369090475731663">"Віджети для заблокованого екрана"</string> <string name="communal_widget_picker_description" msgid="490515450110487871">"Будь-хто бачитиме віджети навіть на заблокованому екрані планшета."</string> - <!-- no translation found for accessibility_action_label_unselect_widget (1041811747619468698) --> - <skip /> + <string name="accessibility_action_label_unselect_widget" msgid="1041811747619468698">"скасувати вибір віджета"</string> <string name="communal_widgets_disclaimer_title" msgid="1150954395585308868">"Віджети для заблокованого екрана"</string> <string name="communal_widgets_disclaimer_text" msgid="1423545475160506349">"Щоб відкрити додаток за допомогою віджета, вам потрібно буде підтвердити особу. Пам’ятайте також, що бачити віджети можуть усі, навіть коли планшет заблоковано. Можливо, деякі віджети не призначені для заблокованого екрана, і додавати їх на нього може бути небезпечно."</string> <string name="communal_widgets_disclaimer_button" msgid="4423059765740780753">"OK"</string> @@ -557,10 +565,8 @@ <string name="media_projection_action_text" msgid="3634906766918186440">"Почати зараз"</string> <string name="empty_shade_text" msgid="8935967157319717412">"Сповіщень немає"</string> <string name="no_unseen_notif_text" msgid="395512586119868682">"Немає нових сповіщень"</string> - <!-- no translation found for adaptive_notification_edu_hun_title (7790738150177329960) --> - <skip /> - <!-- no translation found for adaptive_notification_edu_hun_text (7743367744129536610) --> - <skip /> + <string name="adaptive_notification_edu_hun_title" msgid="7790738150177329960">"Зниження гучності сповіщень увімкнено"</string> + <string name="adaptive_notification_edu_hun_text" msgid="7743367744129536610">"Коли ви отримуєте забагато сповіщень за раз, пристрій автоматично знижує їх гучність і кількість на період до 2 хвилин."</string> <string name="go_to_adaptive_notification_settings" msgid="2423690125178298479">"Вимкнути"</string> <string name="unlock_to_see_notif_text" msgid="7439033907167561227">"Розблокуйте, щоб переглянути старіші"</string> <string name="quick_settings_disclosure_parental_controls" msgid="2114102871438223600">"Цим пристроєм керує батько або мати"</string> @@ -1226,7 +1232,6 @@ <string name="accessibility_fingerprint_bouncer" msgid="7189102492498735519">"Пройдіть автентифікацію. Для цього торкніться сканера відбитків пальців."</string> <string name="ongoing_phone_call_content_description" msgid="5332334388483099947">"Активний телефонний виклик"</string> <string name="mobile_data_settings_title" msgid="3955246641380064901">"Мобільний трафік"</string> - <string name="preference_summary_default_combination" msgid="8453246369903749670">"<xliff:g id="STATE">%1$s</xliff:g>/<xliff:g id="NETWORKMODE">%2$s</xliff:g>"</string> <string name="mobile_data_connection_active" msgid="944490013299018227">"Підключено"</string> <string name="mobile_data_temp_connection_active" msgid="4590222725908806824">"Тимчасово з’єднано"</string> <string name="mobile_data_poor_connection" msgid="819617772268371434">"Погане з’єднання"</string> @@ -1380,7 +1385,10 @@ <string name="touchpad_tutorial_done_button" msgid="176168488821755503">"Готово"</string> <string name="touchpad_tutorial_gesture_done" msgid="4784438360736821255">"Чудово!"</string> <string name="touchpad_back_gesture_action_title" msgid="7199067250654332735">"Назад"</string> - <string name="touchpad_back_gesture_guidance" msgid="4222430588599527272">"Щоб перейти назад, проведіть трьома пальцями вліво або вправо по сенсорній панелі."</string> + <!-- no translation found for touchpad_back_gesture_guidance (6263750214998421587) --> + <skip /> + <!-- no translation found for touchpad_back_gesture_finished (5353616006999726249) --> + <skip /> <string name="touchpad_back_gesture_animation_content_description" msgid="2646107450922379918">"Сенсорна панель із зображенням трьох пальців, що рухаються вправо й уліво"</string> <string name="touchpad_back_gesture_screen_animation_content_description" msgid="4036267494237748710">"Екран пристрою, на якому показано анімацію щодо жесту \"Назад\""</string> <string name="keyboard_backlight_dialog_title" msgid="8273102932345564724">"Підсвічування клавіатури"</string> @@ -1388,28 +1396,16 @@ <string name="home_controls_dream_label" msgid="6567105701292324257">"Автоматизація дому"</string> <string name="home_controls_dream_description" msgid="4644150952104035789">"Швидкий доступ до керування домом через заставку"</string> <string name="volume_undo_action" msgid="5815519725211877114">"Відмінити"</string> - <!-- no translation found for back_edu_toast_content (4530314597378982956) --> - <skip /> - <!-- no translation found for home_edu_toast_content (3381071147871955415) --> - <skip /> - <!-- no translation found for overview_edu_toast_content (5797030644017804518) --> - <skip /> - <!-- no translation found for all_apps_edu_toast_content (8807496014667211562) --> - <skip /> - <!-- no translation found for back_edu_notification_title (5624780717751357278) --> - <skip /> - <!-- no translation found for back_edu_notification_content (2497557451540954068) --> - <skip /> - <!-- no translation found for home_edu_notification_title (6097902076909654045) --> - <skip /> - <!-- no translation found for home_edu_notification_content (6631697734535766588) --> - <skip /> - <!-- no translation found for overview_edu_notification_title (1265824157319562406) --> - <skip /> - <!-- no translation found for overview_edu_notification_content (3578204677648432500) --> - <skip /> - <!-- no translation found for all_apps_edu_notification_title (372262997265569063) --> - <skip /> - <!-- no translation found for all_apps_edu_notification_content (3255070575694025585) --> - <skip /> + <string name="back_edu_toast_content" msgid="4530314597378982956">"Щоб перейти назад, проведіть трьома пальцями вліво або вправо по сенсорній панелі"</string> + <string name="home_edu_toast_content" msgid="3381071147871955415">"Щоб перейти на головний екран, проведіть трьома пальцями вгору по сенсорній панелі"</string> + <string name="overview_edu_toast_content" msgid="5797030644017804518">"Щоб переглянути останні додатки, проведіть трьома пальцями вгору по сенсорній панелі й утримуйте їх"</string> + <string name="all_apps_edu_toast_content" msgid="8807496014667211562">"Щоб переглянути всі додатки, натисніть клавішу дії на клавіатурі"</string> + <string name="back_edu_notification_title" msgid="5624780717751357278">"Щоб повернутися, використовуйте сенсорну панель"</string> + <string name="back_edu_notification_content" msgid="2497557451540954068">"Проведіть трьома пальцями вліво чи вправо. Натисніть, щоб дізнатися про інші жести."</string> + <string name="home_edu_notification_title" msgid="6097902076909654045">"Щоб перейти на головний екран, використовуйте сенсорну панель"</string> + <string name="home_edu_notification_content" msgid="6631697734535766588">"Проведіть трьома пальцями вгору. Натисніть, щоб дізнатися про інші жести."</string> + <string name="overview_edu_notification_title" msgid="1265824157319562406">"Щоб переглянути останні додатки, використовуйте сенсорну панель"</string> + <string name="overview_edu_notification_content" msgid="3578204677648432500">"Проведіть трьома пальцями вгору й утримуйте їх на екрані. Натисніть, щоб дізнатися про інші жести."</string> + <string name="all_apps_edu_notification_title" msgid="372262997265569063">"Щоб переглянути всі додатки, використовуйте клавіатуру"</string> + <string name="all_apps_edu_notification_content" msgid="3255070575694025585">"Будь-коли натисніть клавішу дії. Натисніть, щоб дізнатися про інші жести."</string> </resources> diff --git a/packages/SystemUI/res/values-uk/tiles_states_strings.xml b/packages/SystemUI/res/values-uk/tiles_states_strings.xml index 9e3128366cd6..61e62e4395ce 100644 --- a/packages/SystemUI/res/values-uk/tiles_states_strings.xml +++ b/packages/SystemUI/res/values-uk/tiles_states_strings.xml @@ -56,11 +56,6 @@ <item msgid="5376619709702103243">"Вимкнено"</item> <item msgid="4875147066469902392">"Увімкнено"</item> </string-array> - <string-array name="tile_states_modes"> - <item msgid="7764936419245199023">"Недоступно"</item> - <item msgid="2004750556637773692">"Вимкнено"</item> - <item msgid="8968530753931637871">"Увімкнено"</item> - </string-array> <string-array name="tile_states_flashlight"> <item msgid="3465257127433353857">"Недоступно"</item> <item msgid="5044688398303285224">"Вимкнено"</item> diff --git a/packages/SystemUI/res/values-ur/strings.xml b/packages/SystemUI/res/values-ur/strings.xml index 0530655a56b7..94586b76c8cb 100644 --- a/packages/SystemUI/res/values-ur/strings.xml +++ b/packages/SystemUI/res/values-ur/strings.xml @@ -388,6 +388,9 @@ <string name="performance" msgid="6552785217174378320">"کارکردگی"</string> <string name="user_interface" msgid="3712869377953950887">"یوزر انٹرفیس"</string> <string name="thermal" msgid="6758074791325414831">"تھرمل"</string> + <string name="custom" msgid="3337456985275158299">"حسب ضرورت"</string> + <string name="custom_trace_settings_dialog_title" msgid="2608570500144830554">"حسب ضرورت ٹریس کی ترتیبات"</string> + <string name="restore_default" msgid="5259420807486239755">"ڈیفالٹ بحال کریں"</string> <string name="quick_settings_onehanded_label" msgid="2416537930246274991">"ایک ہاتھ کی وضع"</string> <string name="quick_settings_hearing_devices_label" msgid="7277170419679404129">"سماعت کے آلات"</string> <string name="quick_settings_hearing_devices_connected" msgid="6519069502397037781">"فعال"</string> @@ -429,9 +432,13 @@ <string name="zen_modes_dialog_title" msgid="4159138230418567383">"ترجیحی وضع"</string> <string name="zen_modes_dialog_done" msgid="6654130880256438950">"ہو گیا"</string> <string name="zen_modes_dialog_settings" msgid="2310248023728936697">"ترتیبات"</string> - <!-- no translation found for zen_mode_on (9085304934016242591) --> + <string name="zen_mode_on" msgid="9085304934016242591">"آن ہے"</string> + <string name="zen_mode_off" msgid="1736604456618147306">"آف ہے"</string> + <!-- no translation found for zen_mode_set_up (7457957033034460064) --> <skip /> - <!-- no translation found for zen_mode_off (1736604456618147306) --> + <!-- no translation found for zen_mode_no_manual_invocation (1769975741344633672) --> + <skip /> + <!-- no translation found for zen_mode_active_modes (1625850411578488856) --> <skip /> <string name="zen_priority_introduction" msgid="3159291973383796646">"الارمز، یاددہانیوں، ایونٹس اور آپ کے متعین کردہ کالرز کے علاوہ، آپ آوازوں اور وائبریشنز سے ڈسٹرب نہیں ہوں گے۔ موسیقی، ویڈیوز اور گیمز سمیت آپ ابھی بھی ہر وہ چیز سنیں گے جسے چلانے کا آپ انتخاب کرتے ہیں۔"</string> <string name="zen_alarms_introduction" msgid="3987266042682300470">"الارمز کے علاوہ، آپ آوازوں اور وائبریشنز سے ڈسٹرب نہیں ہوں گے۔ موسیقی، ویڈیوز اور گیمز سمیت آپ ہر وہ چیز سنیں گے جسے چلانے کا آپ انتخاب کرتے ہیں۔"</string> @@ -471,6 +478,8 @@ <string name="keyguard_indication_charging_time_slowly" msgid="301936949731705417">"<xliff:g id="PERCENTAGE">%2$s</xliff:g> • آہستہ چارج ہو رہا ہے • <xliff:g id="CHARGING_TIME_LEFT">%1$s</xliff:g> میں مکمل"</string> <string name="keyguard_indication_charging_time_dock" msgid="3149328898931741271">"<xliff:g id="PERCENTAGE">%2$s</xliff:g> • چارج ہو رہا ہے • <xliff:g id="CHARGING_TIME_LEFT">%1$s</xliff:g> میں مکمل"</string> <string name="accessibility_action_open_communal_hub" msgid="3081702792413787849">"مقفل اسکرین پر ویجیٹس"</string> + <!-- no translation found for accessibility_announcement_communal_widget_added (6911593106099328271) --> + <skip /> <string name="communal_tutorial_indicator_text" msgid="4503010353591430123">"کمیونل ٹیوٹوریل شروع کرنے کے لیے بائیں سوائپ کریں"</string> <string name="cta_tile_button_to_open_widget_editor" msgid="3871562362382963878">"حسب ضرورت بنائیں"</string> <string name="cta_tile_button_to_dismiss" msgid="3377597875997861754">"برخاست کریں"</string> @@ -499,8 +508,7 @@ <string name="accessibility_action_label_place_widget" msgid="1914197458644168978">"منتخب ویجیٹ رکھیں"</string> <string name="communal_widget_picker_title" msgid="1953369090475731663">"مقفل اسکرین کے ویجیٹس"</string> <string name="communal_widget_picker_description" msgid="490515450110487871">"کوئی بھی آپ کی مقفل اسکرین پر ویجیٹ دیکھ سکتا ہے اگرچہ آپ کا ٹیبلیٹ مقفل ہو۔"</string> - <!-- no translation found for accessibility_action_label_unselect_widget (1041811747619468698) --> - <skip /> + <string name="accessibility_action_label_unselect_widget" msgid="1041811747619468698">"ویجیٹ غیر منتخب کریں"</string> <string name="communal_widgets_disclaimer_title" msgid="1150954395585308868">"مقفل اسکرین کے ویجیٹس"</string> <string name="communal_widgets_disclaimer_text" msgid="1423545475160506349">"ویجیٹ کے ذریعے ایپ کھولنے کے لیے آپ کو تصدیق کرنی ہوگی کہ یہ آپ ہی ہیں۔ نیز، ذہن میں رکھیں کہ کوئی بھی انہیں دیکھ سکتا ہے، یہاں تک کہ جب آپ کا ٹیبلیٹ مقفل ہو۔ ہو سکتا ہے کچھ ویجٹس آپ کی لاک اسکرین کے لیے نہ بنائے گئے ہوں اور یہاں شامل کرنا غیر محفوظ ہو سکتا ہے۔"</string> <string name="communal_widgets_disclaimer_button" msgid="4423059765740780753">"سمجھ آ گئی"</string> @@ -557,10 +565,8 @@ <string name="media_projection_action_text" msgid="3634906766918186440">"ابھی شروع کریں"</string> <string name="empty_shade_text" msgid="8935967157319717412">"کوئی اطلاعات نہیں ہیں"</string> <string name="no_unseen_notif_text" msgid="395512586119868682">"کوئی نئی اطلاعات نہیں"</string> - <!-- no translation found for adaptive_notification_edu_hun_title (7790738150177329960) --> - <skip /> - <!-- no translation found for adaptive_notification_edu_hun_text (7743367744129536610) --> - <skip /> + <string name="adaptive_notification_edu_hun_title" msgid="7790738150177329960">"ںوٹیفیکیشن کول ڈاؤن آن ہے"</string> + <string name="adaptive_notification_edu_hun_text" msgid="7743367744129536610">"جب آپ کو ایک ساتھ بہت زیادہ اطلاعات موصول ہوتی ہیں تو آپ کے آلے کا والیوم اور الرٹس خودکار طور پر 2 منٹ تک کم ہو جاتے ہیں۔"</string> <string name="go_to_adaptive_notification_settings" msgid="2423690125178298479">"آف کریں"</string> <string name="unlock_to_see_notif_text" msgid="7439033907167561227">"پرانی اطلاعات دیکھنے کیلئے غیر مقفل کریں"</string> <string name="quick_settings_disclosure_parental_controls" msgid="2114102871438223600">"یہ آلہ آپ کے والدین کے زیر انتظام ہے"</string> @@ -1230,7 +1236,6 @@ <string name="accessibility_fingerprint_bouncer" msgid="7189102492498735519">"توثیق مطلوب ہے۔ توثیق کرنے کے لیے فنگر پرنٹ سینسر کو ٹچ کریں۔"</string> <string name="ongoing_phone_call_content_description" msgid="5332334388483099947">"جاری فون کال"</string> <string name="mobile_data_settings_title" msgid="3955246641380064901">"موبائل ڈیٹا"</string> - <string name="preference_summary_default_combination" msgid="8453246369903749670">"<xliff:g id="NETWORKMODE">%2$s</xliff:g> / <xliff:g id="STATE">%1$s</xliff:g>"</string> <string name="mobile_data_connection_active" msgid="944490013299018227">"منسلک ہے"</string> <string name="mobile_data_temp_connection_active" msgid="4590222725908806824">"عارضی طور پر منسلک ہے"</string> <string name="mobile_data_poor_connection" msgid="819617772268371434">"کمزور کنکشن"</string> @@ -1384,7 +1389,10 @@ <string name="touchpad_tutorial_done_button" msgid="176168488821755503">"ہو گیا"</string> <string name="touchpad_tutorial_gesture_done" msgid="4784438360736821255">"بہترین!"</string> <string name="touchpad_back_gesture_action_title" msgid="7199067250654332735">"واپس جائیں"</string> - <string name="touchpad_back_gesture_guidance" msgid="4222430588599527272">"واپس جانے کے لیے، ٹچ پیڈ پر کہیں بھی تین انگلیوں کی مدد سے دائیں یا بائیں سوائپ کریں۔"</string> + <!-- no translation found for touchpad_back_gesture_guidance (6263750214998421587) --> + <skip /> + <!-- no translation found for touchpad_back_gesture_finished (5353616006999726249) --> + <skip /> <string name="touchpad_back_gesture_animation_content_description" msgid="2646107450922379918">"ٹچ پیڈ دائیں اور بائیں حرکت کرتی ہوئی تین انگلیاں دکھا رہا ہے"</string> <string name="touchpad_back_gesture_screen_animation_content_description" msgid="4036267494237748710">"آلہ کی اسکرین پیچھے جانے کے اشارے کے لیے اینیمیشن دکھا رہی ہے"</string> <string name="keyboard_backlight_dialog_title" msgid="8273102932345564724">"کی بورڈ بیک لائٹ"</string> @@ -1392,28 +1400,16 @@ <string name="home_controls_dream_label" msgid="6567105701292324257">"ہوم کنٹرولز"</string> <string name="home_controls_dream_description" msgid="4644150952104035789">"اسکرین سیور کے بطور اپنے ہوم کنٹرولز تک فوری رسائی حاصل کریں"</string> <string name="volume_undo_action" msgid="5815519725211877114">"کالعدم کریں"</string> - <!-- no translation found for back_edu_toast_content (4530314597378982956) --> - <skip /> - <!-- no translation found for home_edu_toast_content (3381071147871955415) --> - <skip /> - <!-- no translation found for overview_edu_toast_content (5797030644017804518) --> - <skip /> - <!-- no translation found for all_apps_edu_toast_content (8807496014667211562) --> - <skip /> - <!-- no translation found for back_edu_notification_title (5624780717751357278) --> - <skip /> - <!-- no translation found for back_edu_notification_content (2497557451540954068) --> - <skip /> - <!-- no translation found for home_edu_notification_title (6097902076909654045) --> - <skip /> - <!-- no translation found for home_edu_notification_content (6631697734535766588) --> - <skip /> - <!-- no translation found for overview_edu_notification_title (1265824157319562406) --> - <skip /> - <!-- no translation found for overview_edu_notification_content (3578204677648432500) --> - <skip /> - <!-- no translation found for all_apps_edu_notification_title (372262997265569063) --> - <skip /> - <!-- no translation found for all_apps_edu_notification_content (3255070575694025585) --> - <skip /> + <string name="back_edu_toast_content" msgid="4530314597378982956">"واپس جانے کے لیے، ٹچ پیڈ پر تین انگلیوں کی مدد سے بائیں یا دائیں سوائپ کریں"</string> + <string name="home_edu_toast_content" msgid="3381071147871955415">"ہوم پر جانے کے لیے، ٹچ پیڈ پر تین انگلیوں کی مدد سے اوپر سوائپ کریں"</string> + <string name="overview_edu_toast_content" msgid="5797030644017804518">"حالیہ ایپس دیکھنے کے لیے، ٹچ پیڈ پر تین انگلیوں سے اوپر سوائپ کریں اور دبائے رکھیں"</string> + <string name="all_apps_edu_toast_content" msgid="8807496014667211562">"اپنی سبھی ایپس دیکھنے کے لیے، اپنے کی بورڈ پر ایکشن کلید دبائیں"</string> + <string name="back_edu_notification_title" msgid="5624780717751357278">"واپس جانے کے لیے اپنے ٹچ پیڈ کا استعمال کریں"</string> + <string name="back_edu_notification_content" msgid="2497557451540954068">"تین انگلیوں سے دائیں یا بائیں طرف سوائپ کریں۔ مزید اشارے جاننے کے لیے تھپتھپائیں۔"</string> + <string name="home_edu_notification_title" msgid="6097902076909654045">"ہوم پر جانے کے لیے اپنے ٹچ پیڈ کا استعمال کریں"</string> + <string name="home_edu_notification_content" msgid="6631697734535766588">"تین انگلیوں سے اوپر سوائپ کریں۔ مزید اشارے جاننے کے لیے تھپتھپائیں۔"</string> + <string name="overview_edu_notification_title" msgid="1265824157319562406">"حالیہ ایپس دیکھنے کے لیے اپنے ٹچ پیڈ کا استعمال کریں"</string> + <string name="overview_edu_notification_content" msgid="3578204677648432500">"تین انگلیوں سے اوپر کی طرف سوائپ کریں اور دبائے رکھیں۔ مزید اشارے جاننے کے لیے تھپتھپائیں۔"</string> + <string name="all_apps_edu_notification_title" msgid="372262997265569063">"سبھی ایپس دیکھنے کے لیے اپنے کی بورڈ کا استعمال کریں"</string> + <string name="all_apps_edu_notification_content" msgid="3255070575694025585">"کسی بھی وقت ایکشن کلید دبائیں۔ مزید اشارے جاننے کے لیے تھپتھپائیں۔"</string> </resources> diff --git a/packages/SystemUI/res/values-ur/tiles_states_strings.xml b/packages/SystemUI/res/values-ur/tiles_states_strings.xml index e398b2f84803..ebbc30ebca58 100644 --- a/packages/SystemUI/res/values-ur/tiles_states_strings.xml +++ b/packages/SystemUI/res/values-ur/tiles_states_strings.xml @@ -56,11 +56,6 @@ <item msgid="5376619709702103243">"آف ہے"</item> <item msgid="4875147066469902392">"آن ہے"</item> </string-array> - <string-array name="tile_states_modes"> - <item msgid="7764936419245199023">"دستیاب نہیں ہے"</item> - <item msgid="2004750556637773692">"آف ہے"</item> - <item msgid="8968530753931637871">"آن ہے"</item> - </string-array> <string-array name="tile_states_flashlight"> <item msgid="3465257127433353857">"دستیاب نہیں ہے"</item> <item msgid="5044688398303285224">"آف ہے"</item> diff --git a/packages/SystemUI/res/values-uz/strings.xml b/packages/SystemUI/res/values-uz/strings.xml index 11c0dff48f84..3f6077622404 100644 --- a/packages/SystemUI/res/values-uz/strings.xml +++ b/packages/SystemUI/res/values-uz/strings.xml @@ -388,6 +388,9 @@ <string name="performance" msgid="6552785217174378320">"Unumdorlik"</string> <string name="user_interface" msgid="3712869377953950887">"Foydalanuvchi interfeysi"</string> <string name="thermal" msgid="6758074791325414831">"Termal"</string> + <string name="custom" msgid="3337456985275158299">"Maxsus"</string> + <string name="custom_trace_settings_dialog_title" msgid="2608570500144830554">"Maxsus trassirovka sozlamalari"</string> + <string name="restore_default" msgid="5259420807486239755">"Asliga qaytarish"</string> <string name="quick_settings_onehanded_label" msgid="2416537930246274991">"Ixcham rejim"</string> <string name="quick_settings_hearing_devices_label" msgid="7277170419679404129">"Eshitish qurilmalari"</string> <string name="quick_settings_hearing_devices_connected" msgid="6519069502397037781">"Faol"</string> @@ -429,9 +432,13 @@ <string name="zen_modes_dialog_title" msgid="4159138230418567383">"Muhim rejimlar"</string> <string name="zen_modes_dialog_done" msgid="6654130880256438950">"Tayyor"</string> <string name="zen_modes_dialog_settings" msgid="2310248023728936697">"Sozlamalar"</string> - <!-- no translation found for zen_mode_on (9085304934016242591) --> + <string name="zen_mode_on" msgid="9085304934016242591">"Yoniq"</string> + <string name="zen_mode_off" msgid="1736604456618147306">"Yoqilmagan"</string> + <!-- no translation found for zen_mode_set_up (7457957033034460064) --> <skip /> - <!-- no translation found for zen_mode_off (1736604456618147306) --> + <!-- no translation found for zen_mode_no_manual_invocation (1769975741344633672) --> + <skip /> + <!-- no translation found for zen_mode_active_modes (1625850411578488856) --> <skip /> <string name="zen_priority_introduction" msgid="3159291973383796646">"Turli ovoz va tebranishlar endi sizni bezovta qilmaydi. Biroq, signallar, eslatmalar, tadbirlar haqidagi bildirishnomalar va siz tanlagan abonentlardan kelgan chaqiruvlar bundan mustasno. Lekin, ijro etiladigan barcha narsalar, jumladan, musiqa, video va o‘yinlar ovozi eshitiladi."</string> <string name="zen_alarms_introduction" msgid="3987266042682300470">"Turli ovoz va tebranishlar endi sizni bezovta qilmaydi. Biroq, signallar bundan mustasno. Lekin, ijro etiladigan barcha narsalar, jumladan, musiqa, video va o‘yinlar ovozi eshitiladi."</string> @@ -471,6 +478,8 @@ <string name="keyguard_indication_charging_time_slowly" msgid="301936949731705417">"<xliff:g id="PERCENTAGE">%2$s</xliff:g> • Sekin quvvat olmoqda • <xliff:g id="CHARGING_TIME_LEFT">%1$s</xliff:g> qoldi"</string> <string name="keyguard_indication_charging_time_dock" msgid="3149328898931741271">"<xliff:g id="PERCENTAGE">%2$s</xliff:g> • Quvvat olmoqda • <xliff:g id="CHARGING_TIME_LEFT">%1$s</xliff:g> qoldi"</string> <string name="accessibility_action_open_communal_hub" msgid="3081702792413787849">"Ekran qulfidagi vidjetlar"</string> + <!-- no translation found for accessibility_announcement_communal_widget_added (6911593106099328271) --> + <skip /> <string name="communal_tutorial_indicator_text" msgid="4503010353591430123">"Qoʻllanma bilan tanishish uchun chapga suring"</string> <string name="cta_tile_button_to_open_widget_editor" msgid="3871562362382963878">"Moslash"</string> <string name="cta_tile_button_to_dismiss" msgid="3377597875997861754">"Yopish"</string> @@ -499,8 +508,7 @@ <string name="accessibility_action_label_place_widget" msgid="1914197458644168978">"tanlangan vidjetni joylash"</string> <string name="communal_widget_picker_title" msgid="1953369090475731663">"Ekran qulfi vidjetlari"</string> <string name="communal_widget_picker_description" msgid="490515450110487871">"Ekran quflidagi vidjetlar hammaga koʻrinadi, hatto planshet qulflanganda ham."</string> - <!-- no translation found for accessibility_action_label_unselect_widget (1041811747619468698) --> - <skip /> + <string name="accessibility_action_label_unselect_widget" msgid="1041811747619468698">"vidjetni bekor qilish"</string> <string name="communal_widgets_disclaimer_title" msgid="1150954395585308868">"Ekran qulfi vidjetlari"</string> <string name="communal_widgets_disclaimer_text" msgid="1423545475160506349">"Ilovani vidjet orqali ochish uchun shaxsingizni tasdiqlashingiz kerak. Shuningdek, planshet qulflanganda ham bu axborotlar hammaga koʻrinishini unutmang. Ayrim vidjetlar ekran qulfiga moslanmagan va ularni bu yerda chiqarish xavfli boʻlishi mumkin."</string> <string name="communal_widgets_disclaimer_button" msgid="4423059765740780753">"OK"</string> @@ -557,10 +565,8 @@ <string name="media_projection_action_text" msgid="3634906766918186440">"Boshlash"</string> <string name="empty_shade_text" msgid="8935967157319717412">"Bildirishnomalar yo‘q"</string> <string name="no_unseen_notif_text" msgid="395512586119868682">"Yangi bildirishoma yoʻq"</string> - <!-- no translation found for adaptive_notification_edu_hun_title (7790738150177329960) --> - <skip /> - <!-- no translation found for adaptive_notification_edu_hun_text (7743367744129536610) --> - <skip /> + <string name="adaptive_notification_edu_hun_title" msgid="7790738150177329960">"Bildirishnomalarni sekinlatish yoniq"</string> + <string name="adaptive_notification_edu_hun_text" msgid="7743367744129536610">"Bir vaqtda juda koʻp bildirishnoma olsangiz, qurilmangiz tovushi va ogohlantirishlar 2 daqiqagacha avtomatik pasaytiriladi."</string> <string name="go_to_adaptive_notification_settings" msgid="2423690125178298479">"Faolsizlantirish"</string> <string name="unlock_to_see_notif_text" msgid="7439033907167561227">"Eskilarini koʻrish uchun qulfni yeching"</string> <string name="quick_settings_disclosure_parental_controls" msgid="2114102871438223600">"Bu qurilmani ota-onangiz boshqaradi"</string> @@ -1226,7 +1232,6 @@ <string name="accessibility_fingerprint_bouncer" msgid="7189102492498735519">"Haqiqiylikni tekshirish talab etiladi. Autentifikatsiya uchun barmoq izi skaneriga tegining."</string> <string name="ongoing_phone_call_content_description" msgid="5332334388483099947">"Joriy telefon chaqiruvi"</string> <string name="mobile_data_settings_title" msgid="3955246641380064901">"Mobil internet"</string> - <string name="preference_summary_default_combination" msgid="8453246369903749670">"<xliff:g id="STATE">%1$s</xliff:g> / <xliff:g id="NETWORKMODE">%2$s</xliff:g>"</string> <string name="mobile_data_connection_active" msgid="944490013299018227">"Ulangan"</string> <string name="mobile_data_temp_connection_active" msgid="4590222725908806824">"Vaqtincha ulangan"</string> <string name="mobile_data_poor_connection" msgid="819617772268371434">"Aloqa beqaror"</string> @@ -1380,7 +1385,10 @@ <string name="touchpad_tutorial_done_button" msgid="176168488821755503">"Tayyor"</string> <string name="touchpad_tutorial_gesture_done" msgid="4784438360736821255">"Barakalla!"</string> <string name="touchpad_back_gesture_action_title" msgid="7199067250654332735">"Orqaga qaytish"</string> - <string name="touchpad_back_gesture_guidance" msgid="4222430588599527272">"Ortga qaytish uchun sensorli panelda uchta barmoqni chapga yoki oʻngga suring."</string> + <!-- no translation found for touchpad_back_gesture_guidance (6263750214998421587) --> + <skip /> + <!-- no translation found for touchpad_back_gesture_finished (5353616006999726249) --> + <skip /> <string name="touchpad_back_gesture_animation_content_description" msgid="2646107450922379918">"Sensorli panelda uchta barmoq chapga va oʻngga harakatlanishi"</string> <string name="touchpad_back_gesture_screen_animation_content_description" msgid="4036267494237748710">"Qurilma ekranidagi ortga qaytish ishorasi animatsiyasi"</string> <string name="keyboard_backlight_dialog_title" msgid="8273102932345564724">"Klaviatura orqa yoritkichi"</string> @@ -1388,28 +1396,16 @@ <string name="home_controls_dream_label" msgid="6567105701292324257">"Uy boshqaruvi"</string> <string name="home_controls_dream_description" msgid="4644150952104035789">"Uy boshqaruvi tugmalarini ekran lavhasida tezkor oching"</string> <string name="volume_undo_action" msgid="5815519725211877114">"Bekor qilish"</string> - <!-- no translation found for back_edu_toast_content (4530314597378982956) --> - <skip /> - <!-- no translation found for home_edu_toast_content (3381071147871955415) --> - <skip /> - <!-- no translation found for overview_edu_toast_content (5797030644017804518) --> - <skip /> - <!-- no translation found for all_apps_edu_toast_content (8807496014667211562) --> - <skip /> - <!-- no translation found for back_edu_notification_title (5624780717751357278) --> - <skip /> - <!-- no translation found for back_edu_notification_content (2497557451540954068) --> - <skip /> - <!-- no translation found for home_edu_notification_title (6097902076909654045) --> - <skip /> - <!-- no translation found for home_edu_notification_content (6631697734535766588) --> - <skip /> - <!-- no translation found for overview_edu_notification_title (1265824157319562406) --> - <skip /> - <!-- no translation found for overview_edu_notification_content (3578204677648432500) --> - <skip /> - <!-- no translation found for all_apps_edu_notification_title (372262997265569063) --> - <skip /> - <!-- no translation found for all_apps_edu_notification_content (3255070575694025585) --> - <skip /> + <string name="back_edu_toast_content" msgid="4530314597378982956">"Orqaga qaytish uchun sensorli panelda uchta barmoq bilan chapga yoki oʻngga suring"</string> + <string name="home_edu_toast_content" msgid="3381071147871955415">"Bosh ekranga qaytish uchun sensorli panelda uchta barmoq bilan chapga yoki oʻngga suring"</string> + <string name="overview_edu_toast_content" msgid="5797030644017804518">"Oxirgi ilovalarni koʻrish uchun sensorli panelda uchta barmoq bilan tepaga surib, bosib turing"</string> + <string name="all_apps_edu_toast_content" msgid="8807496014667211562">"Barcha ishoralarni koʻrish uchun klaviaturadagi amal tugmasini bosing"</string> + <string name="back_edu_notification_title" msgid="5624780717751357278">"Sensorli panel orqali orqaga qaytish"</string> + <string name="back_edu_notification_content" msgid="2497557451540954068">"Uchta barmoq bilan chapga yoki oʻngga suring. Boshqa ishoralar bilan tanishish uchun bosing."</string> + <string name="home_edu_notification_title" msgid="6097902076909654045">"Sensorli panel orqali bosh ekranga qaytish"</string> + <string name="home_edu_notification_content" msgid="6631697734535766588">"Uchta barmoq bilan tepaga suring. Boshqa ishoralar bilan tanishish uchun bosing."</string> + <string name="overview_edu_notification_title" msgid="1265824157319562406">"Sensorli panel orqali oxirgi ilovalarni koʻrish"</string> + <string name="overview_edu_notification_content" msgid="3578204677648432500">"Uchta barmoq bilan tepaga surib, bosib turing. Boshqa ishoralar bilan tanishish uchun bosing."</string> + <string name="all_apps_edu_notification_title" msgid="372262997265569063">"Klaviatura orqali barcha ilovalarni koʻrish"</string> + <string name="all_apps_edu_notification_content" msgid="3255070575694025585">"Amal tugmasini istalganda bosing. Boshqa ishoralar bilan tanishish uchun bosing."</string> </resources> diff --git a/packages/SystemUI/res/values-uz/tiles_states_strings.xml b/packages/SystemUI/res/values-uz/tiles_states_strings.xml index 49b774fb79a0..2ae811233176 100644 --- a/packages/SystemUI/res/values-uz/tiles_states_strings.xml +++ b/packages/SystemUI/res/values-uz/tiles_states_strings.xml @@ -56,11 +56,6 @@ <item msgid="5376619709702103243">"Oʻchiq"</item> <item msgid="4875147066469902392">"Yoniq"</item> </string-array> - <string-array name="tile_states_modes"> - <item msgid="7764936419245199023">"Mavjud emas"</item> - <item msgid="2004750556637773692">"Oʻchiq"</item> - <item msgid="8968530753931637871">"Yoniq"</item> - </string-array> <string-array name="tile_states_flashlight"> <item msgid="3465257127433353857">"Ishlamaydi"</item> <item msgid="5044688398303285224">"Oʻchiq"</item> diff --git a/packages/SystemUI/res/values-vi/strings.xml b/packages/SystemUI/res/values-vi/strings.xml index 5bc1e03bf9bb..dcf8051d692c 100644 --- a/packages/SystemUI/res/values-vi/strings.xml +++ b/packages/SystemUI/res/values-vi/strings.xml @@ -388,6 +388,9 @@ <string name="performance" msgid="6552785217174378320">"Hiệu suất"</string> <string name="user_interface" msgid="3712869377953950887">"Giao diện người dùng"</string> <string name="thermal" msgid="6758074791325414831">"Nhiệt"</string> + <string name="custom" msgid="3337456985275158299">"Tuỳ chỉnh"</string> + <string name="custom_trace_settings_dialog_title" msgid="2608570500144830554">"Cài đặt dấu vết tuỳ chỉnh"</string> + <string name="restore_default" msgid="5259420807486239755">"Khôi phục giá trị mặc định"</string> <string name="quick_settings_onehanded_label" msgid="2416537930246274991">"Chế độ một tay"</string> <string name="quick_settings_hearing_devices_label" msgid="7277170419679404129">"Thiết bị trợ thính"</string> <string name="quick_settings_hearing_devices_connected" msgid="6519069502397037781">"Đang hoạt động"</string> @@ -429,9 +432,13 @@ <string name="zen_modes_dialog_title" msgid="4159138230418567383">"Chế độ ưu tiên"</string> <string name="zen_modes_dialog_done" msgid="6654130880256438950">"Xong"</string> <string name="zen_modes_dialog_settings" msgid="2310248023728936697">"Cài đặt"</string> - <!-- no translation found for zen_mode_on (9085304934016242591) --> + <string name="zen_mode_on" msgid="9085304934016242591">"Đang bật"</string> + <string name="zen_mode_off" msgid="1736604456618147306">"Đang tắt"</string> + <!-- no translation found for zen_mode_set_up (7457957033034460064) --> <skip /> - <!-- no translation found for zen_mode_off (1736604456618147306) --> + <!-- no translation found for zen_mode_no_manual_invocation (1769975741344633672) --> + <skip /> + <!-- no translation found for zen_mode_active_modes (1625850411578488856) --> <skip /> <string name="zen_priority_introduction" msgid="3159291973383796646">"Bạn sẽ không bị làm phiền bởi âm thanh và tiếng rung, ngoại trừ báo thức, lời nhắc, sự kiện và người gọi mà bạn chỉ định. Bạn sẽ vẫn nghe thấy mọi thứ bạn chọn phát, bao gồm nhạc, video và trò chơi."</string> <string name="zen_alarms_introduction" msgid="3987266042682300470">"Bạn sẽ không bị làm phiền bởi âm thanh và tiếng rung, ngoại trừ báo thức. Bạn sẽ vẫn nghe thấy mọi thứ bạn chọn phát, bao gồm nhạc, video và trò chơi."</string> @@ -471,6 +478,8 @@ <string name="keyguard_indication_charging_time_slowly" msgid="301936949731705417">"<xliff:g id="PERCENTAGE">%2$s</xliff:g> • Đang sạc chậm • Sẽ đầy sau <xliff:g id="CHARGING_TIME_LEFT">%1$s</xliff:g>"</string> <string name="keyguard_indication_charging_time_dock" msgid="3149328898931741271">"<xliff:g id="PERCENTAGE">%2$s</xliff:g> • Đang sạc • Sẽ đầy sau <xliff:g id="CHARGING_TIME_LEFT">%1$s</xliff:g>"</string> <string name="accessibility_action_open_communal_hub" msgid="3081702792413787849">"Các tiện ích trên màn hình khoá"</string> + <!-- no translation found for accessibility_announcement_communal_widget_added (6911593106099328271) --> + <skip /> <string name="communal_tutorial_indicator_text" msgid="4503010353591430123">"Vuốt sang trái để bắt đầu xem hướng dẫn chung"</string> <string name="cta_tile_button_to_open_widget_editor" msgid="3871562362382963878">"Tuỳ chỉnh"</string> <string name="cta_tile_button_to_dismiss" msgid="3377597875997861754">"Đóng"</string> @@ -499,8 +508,7 @@ <string name="accessibility_action_label_place_widget" msgid="1914197458644168978">"đặt tiện ích đã chọn vào vị trí"</string> <string name="communal_widget_picker_title" msgid="1953369090475731663">"Tiện ích trên màn hình khoá"</string> <string name="communal_widget_picker_description" msgid="490515450110487871">"Ai cũng thấy được các tiện ích trên màn hình khoá, dù bạn đã khoá máy tính bảng."</string> - <!-- no translation found for accessibility_action_label_unselect_widget (1041811747619468698) --> - <skip /> + <string name="accessibility_action_label_unselect_widget" msgid="1041811747619468698">"bỏ chọn tiện ích"</string> <string name="communal_widgets_disclaimer_title" msgid="1150954395585308868">"Tiện ích trên màn hình khoá"</string> <string name="communal_widgets_disclaimer_text" msgid="1423545475160506349">"Để dùng tiện ích mở một ứng dụng, bạn cần xác minh danh tính của mình. Ngoài ra, hãy lưu ý rằng bất kỳ ai cũng có thể xem các tiện ích này, ngay cả khi máy tính bảng của bạn được khoá. Một số tiện ích có thể không dành cho màn hình khoá và không an toàn khi thêm vào đây."</string> <string name="communal_widgets_disclaimer_button" msgid="4423059765740780753">"Tôi hiểu"</string> @@ -557,10 +565,8 @@ <string name="media_projection_action_text" msgid="3634906766918186440">"Bắt đầu ngay"</string> <string name="empty_shade_text" msgid="8935967157319717412">"Không có thông báo nào"</string> <string name="no_unseen_notif_text" msgid="395512586119868682">"Không có thông báo mới"</string> - <!-- no translation found for adaptive_notification_edu_hun_title (7790738150177329960) --> - <skip /> - <!-- no translation found for adaptive_notification_edu_hun_text (7743367744129536610) --> - <skip /> + <string name="adaptive_notification_edu_hun_title" msgid="7790738150177329960">"Chế độ Giảm dần âm lượng thông báo đang bật"</string> + <string name="adaptive_notification_edu_hun_text" msgid="7743367744129536610">"Khi bạn nhận quá nhiều thông báo cùng lúc, âm lượng và cảnh báo tự động giảm trong tối đa 2 phút."</string> <string name="go_to_adaptive_notification_settings" msgid="2423690125178298479">"Tắt"</string> <string name="unlock_to_see_notif_text" msgid="7439033907167561227">"Mở khoá để xem thông báo cũ"</string> <string name="quick_settings_disclosure_parental_controls" msgid="2114102871438223600">"Thiết bị này do cha mẹ của bạn quản lý"</string> @@ -1226,7 +1232,6 @@ <string name="accessibility_fingerprint_bouncer" msgid="7189102492498735519">"Bạn cần phải xác thực. Hãy chạm vào cảm biến vân tay để xác thực."</string> <string name="ongoing_phone_call_content_description" msgid="5332334388483099947">"Đang gọi điện thoại"</string> <string name="mobile_data_settings_title" msgid="3955246641380064901">"Dữ liệu di động"</string> - <string name="preference_summary_default_combination" msgid="8453246369903749670">"<xliff:g id="STATE">%1$s</xliff:g>/<xliff:g id="NETWORKMODE">%2$s</xliff:g>"</string> <string name="mobile_data_connection_active" msgid="944490013299018227">"Đã kết nối"</string> <string name="mobile_data_temp_connection_active" msgid="4590222725908806824">"Tạm thời có kết nối"</string> <string name="mobile_data_poor_connection" msgid="819617772268371434">"Kết nối kém"</string> @@ -1380,7 +1385,10 @@ <string name="touchpad_tutorial_done_button" msgid="176168488821755503">"Xong"</string> <string name="touchpad_tutorial_gesture_done" msgid="4784438360736821255">"Tuyệt vời!"</string> <string name="touchpad_back_gesture_action_title" msgid="7199067250654332735">"Quay lại"</string> - <string name="touchpad_back_gesture_guidance" msgid="4222430588599527272">"Để quay lại, hãy vuốt sang trái hoặc sang phải bằng 3 ngón tay ở vị trí bất kỳ trên bàn di chuột."</string> + <!-- no translation found for touchpad_back_gesture_guidance (6263750214998421587) --> + <skip /> + <!-- no translation found for touchpad_back_gesture_finished (5353616006999726249) --> + <skip /> <string name="touchpad_back_gesture_animation_content_description" msgid="2646107450922379918">"Minh hoạ thao tác di chuyển sang phải và sang trái bằng 3 ngón tay trên bàn di chuột"</string> <string name="touchpad_back_gesture_screen_animation_content_description" msgid="4036267494237748710">"Màn hình thiết bị hiện ảnh động minh hoạ cử chỉ quay lại"</string> <string name="keyboard_backlight_dialog_title" msgid="8273102932345564724">"Đèn nền bàn phím"</string> @@ -1388,28 +1396,16 @@ <string name="home_controls_dream_label" msgid="6567105701292324257">"Điều khiển nhà"</string> <string name="home_controls_dream_description" msgid="4644150952104035789">"Điều khiển nhà nhanh bằng trình bảo vệ màn hình"</string> <string name="volume_undo_action" msgid="5815519725211877114">"Huỷ"</string> - <!-- no translation found for back_edu_toast_content (4530314597378982956) --> - <skip /> - <!-- no translation found for home_edu_toast_content (3381071147871955415) --> - <skip /> - <!-- no translation found for overview_edu_toast_content (5797030644017804518) --> - <skip /> - <!-- no translation found for all_apps_edu_toast_content (8807496014667211562) --> - <skip /> - <!-- no translation found for back_edu_notification_title (5624780717751357278) --> - <skip /> - <!-- no translation found for back_edu_notification_content (2497557451540954068) --> - <skip /> - <!-- no translation found for home_edu_notification_title (6097902076909654045) --> - <skip /> - <!-- no translation found for home_edu_notification_content (6631697734535766588) --> - <skip /> - <!-- no translation found for overview_edu_notification_title (1265824157319562406) --> - <skip /> - <!-- no translation found for overview_edu_notification_content (3578204677648432500) --> - <skip /> - <!-- no translation found for all_apps_edu_notification_title (372262997265569063) --> - <skip /> - <!-- no translation found for all_apps_edu_notification_content (3255070575694025585) --> - <skip /> + <string name="back_edu_toast_content" msgid="4530314597378982956">"Để quay lại, hãy dùng 3 ngón tay vuốt sang trái hoặc phải trên bàn di chuột"</string> + <string name="home_edu_toast_content" msgid="3381071147871955415">"Để trở về màn hình chính, hãy dùng 3 ngón tay vuốt lên trên bàn di chuột"</string> + <string name="overview_edu_toast_content" msgid="5797030644017804518">"Để xem các ứng dụng gần đây, hãy dùng 3 ngón tay vuốt lên và giữ trên bàn di chuột"</string> + <string name="all_apps_edu_toast_content" msgid="8807496014667211562">"Để xem tất cả ứng dụng của bạn, hãy nhấn phím hành động trên bàn phím"</string> + <string name="back_edu_notification_title" msgid="5624780717751357278">"Dùng bàn di chuột để quay lại"</string> + <string name="back_edu_notification_content" msgid="2497557451540954068">"Dùng 3 ngón tay vuốt sang trái hoặc sang phải. Hãy nhấn để tìm hiểu các cử chỉ khác."</string> + <string name="home_edu_notification_title" msgid="6097902076909654045">"Dùng bàn di chuột để chuyển đến màn hình chính"</string> + <string name="home_edu_notification_content" msgid="6631697734535766588">"Dùng 3 ngón tay vuốt lên. Hãy nhấn để tìm hiểu các cử chỉ khác."</string> + <string name="overview_edu_notification_title" msgid="1265824157319562406">"Dùng bàn di chuột để xem các ứng dụng gần đây"</string> + <string name="overview_edu_notification_content" msgid="3578204677648432500">"Dùng 3 ngón tay vuốt lên và giữ. Hãy nhấn để tìm hiểu các cử chỉ khác."</string> + <string name="all_apps_edu_notification_title" msgid="372262997265569063">"Sử dụng bàn phím để xem tất cả ứng dụng"</string> + <string name="all_apps_edu_notification_content" msgid="3255070575694025585">"Nhấn phím hành động bất cứ lúc nào. Hãy nhấn để tìm hiểu các cử chỉ khác."</string> </resources> diff --git a/packages/SystemUI/res/values-vi/tiles_states_strings.xml b/packages/SystemUI/res/values-vi/tiles_states_strings.xml index e68351874d52..d9d8af1d644c 100644 --- a/packages/SystemUI/res/values-vi/tiles_states_strings.xml +++ b/packages/SystemUI/res/values-vi/tiles_states_strings.xml @@ -56,11 +56,6 @@ <item msgid="5376619709702103243">"Đang tắt"</item> <item msgid="4875147066469902392">"Đang bật"</item> </string-array> - <string-array name="tile_states_modes"> - <item msgid="7764936419245199023">"Không có"</item> - <item msgid="2004750556637773692">"Đang tắt"</item> - <item msgid="8968530753931637871">"Đang bật"</item> - </string-array> <string-array name="tile_states_flashlight"> <item msgid="3465257127433353857">"Không hoạt động"</item> <item msgid="5044688398303285224">"Đang tắt"</item> diff --git a/packages/SystemUI/res/values-zh-rCN/strings.xml b/packages/SystemUI/res/values-zh-rCN/strings.xml index 1a58804a0b92..6162da8304b6 100644 --- a/packages/SystemUI/res/values-zh-rCN/strings.xml +++ b/packages/SystemUI/res/values-zh-rCN/strings.xml @@ -388,6 +388,9 @@ <string name="performance" msgid="6552785217174378320">"性能"</string> <string name="user_interface" msgid="3712869377953950887">"界面"</string> <string name="thermal" msgid="6758074791325414831">"散热"</string> + <string name="custom" msgid="3337456985275158299">"自定义"</string> + <string name="custom_trace_settings_dialog_title" msgid="2608570500144830554">"自定义跟踪记录设置"</string> + <string name="restore_default" msgid="5259420807486239755">"恢复默认设置"</string> <string name="quick_settings_onehanded_label" msgid="2416537930246274991">"单手模式"</string> <string name="quick_settings_hearing_devices_label" msgid="7277170419679404129">"助听装置"</string> <string name="quick_settings_hearing_devices_connected" msgid="6519069502397037781">"已连接"</string> @@ -429,9 +432,13 @@ <string name="zen_modes_dialog_title" msgid="4159138230418567383">"优先模式"</string> <string name="zen_modes_dialog_done" msgid="6654130880256438950">"完成"</string> <string name="zen_modes_dialog_settings" msgid="2310248023728936697">"设置"</string> - <!-- no translation found for zen_mode_on (9085304934016242591) --> + <string name="zen_mode_on" msgid="9085304934016242591">"已开启"</string> + <string name="zen_mode_off" msgid="1736604456618147306">"已关闭"</string> + <!-- no translation found for zen_mode_set_up (7457957033034460064) --> <skip /> - <!-- no translation found for zen_mode_off (1736604456618147306) --> + <!-- no translation found for zen_mode_no_manual_invocation (1769975741344633672) --> + <skip /> + <!-- no translation found for zen_mode_active_modes (1625850411578488856) --> <skip /> <string name="zen_priority_introduction" msgid="3159291973383796646">"您将不会受到声音和振动的打扰(闹钟、提醒、活动和所指定来电者的相关提示音除外)。您依然可以听到您选择播放的任何内容(包括音乐、视频和游戏)的相关音效。"</string> <string name="zen_alarms_introduction" msgid="3987266042682300470">"您将不会受到声音和振动的打扰(闹钟提示音除外)。您依然可以听到您选择播放的任何内容(包括音乐、视频和游戏)的相关音效。"</string> @@ -471,6 +478,8 @@ <string name="keyguard_indication_charging_time_slowly" msgid="301936949731705417">"<xliff:g id="PERCENTAGE">%2$s</xliff:g> • 正在慢速充电 • 将于 <xliff:g id="CHARGING_TIME_LEFT">%1$s</xliff:g>后充满"</string> <string name="keyguard_indication_charging_time_dock" msgid="3149328898931741271">"<xliff:g id="PERCENTAGE">%2$s</xliff:g> • 正在充电 • 将于 <xliff:g id="CHARGING_TIME_LEFT">%1$s</xliff:g>后充满"</string> <string name="accessibility_action_open_communal_hub" msgid="3081702792413787849">"锁定屏幕上的微件"</string> + <!-- no translation found for accessibility_announcement_communal_widget_added (6911593106099328271) --> + <skip /> <string name="communal_tutorial_indicator_text" msgid="4503010353591430123">"向左滑动即可启动公共教程"</string> <string name="cta_tile_button_to_open_widget_editor" msgid="3871562362382963878">"自定义"</string> <string name="cta_tile_button_to_dismiss" msgid="3377597875997861754">"关闭"</string> @@ -499,8 +508,7 @@ <string name="accessibility_action_label_place_widget" msgid="1914197458644168978">"放置所选微件"</string> <string name="communal_widget_picker_title" msgid="1953369090475731663">"锁屏微件"</string> <string name="communal_widget_picker_description" msgid="490515450110487871">"任何人都可以查看锁屏上的微件,即使平板电脑已锁定。"</string> - <!-- no translation found for accessibility_action_label_unselect_widget (1041811747619468698) --> - <skip /> + <string name="accessibility_action_label_unselect_widget" msgid="1041811747619468698">"取消选中微件"</string> <string name="communal_widgets_disclaimer_title" msgid="1150954395585308868">"锁定的屏幕中的微件"</string> <string name="communal_widgets_disclaimer_text" msgid="1423545475160506349">"若要使用微件打开应用,您需要验证是您本人在操作。另外请注意,任何人都可以查看此类微件,即使您的平板电脑已锁定。有些微件可能不适合显示在锁定的屏幕中,因此添加到这里可能不安全。"</string> <string name="communal_widgets_disclaimer_button" msgid="4423059765740780753">"知道了"</string> @@ -557,10 +565,8 @@ <string name="media_projection_action_text" msgid="3634906766918186440">"立即开始"</string> <string name="empty_shade_text" msgid="8935967157319717412">"没有通知"</string> <string name="no_unseen_notif_text" msgid="395512586119868682">"没有新通知"</string> - <!-- no translation found for adaptive_notification_edu_hun_title (7790738150177329960) --> - <skip /> - <!-- no translation found for adaptive_notification_edu_hun_text (7743367744129536610) --> - <skip /> + <string name="adaptive_notification_edu_hun_title" msgid="7790738150177329960">"“通知音量渐降”设置已开启"</string> + <string name="adaptive_notification_edu_hun_text" msgid="7743367744129536610">"当您一次收到过多通知时,设备音量会自动降低,提醒次数也会自动减少,这种状况最长可持续 2 分钟。"</string> <string name="go_to_adaptive_notification_settings" msgid="2423690125178298479">"关闭"</string> <string name="unlock_to_see_notif_text" msgid="7439033907167561227">"解锁即可查看旧通知"</string> <string name="quick_settings_disclosure_parental_controls" msgid="2114102871438223600">"此设备由您的家长管理"</string> @@ -1226,7 +1232,6 @@ <string name="accessibility_fingerprint_bouncer" msgid="7189102492498735519">"需要进行身份验证。请轻触指纹传感器以验证身份。"</string> <string name="ongoing_phone_call_content_description" msgid="5332334388483099947">"正在进行通话"</string> <string name="mobile_data_settings_title" msgid="3955246641380064901">"移动数据网络"</string> - <string name="preference_summary_default_combination" msgid="8453246369903749670">"<xliff:g id="STATE">%1$s</xliff:g> / <xliff:g id="NETWORKMODE">%2$s</xliff:g>"</string> <string name="mobile_data_connection_active" msgid="944490013299018227">"已连接"</string> <string name="mobile_data_temp_connection_active" msgid="4590222725908806824">"已暂时连接"</string> <string name="mobile_data_poor_connection" msgid="819617772268371434">"连接状况不佳"</string> @@ -1380,7 +1385,10 @@ <string name="touchpad_tutorial_done_button" msgid="176168488821755503">"完成"</string> <string name="touchpad_tutorial_gesture_done" msgid="4784438360736821255">"太棒了!"</string> <string name="touchpad_back_gesture_action_title" msgid="7199067250654332735">"返回"</string> - <string name="touchpad_back_gesture_guidance" msgid="4222430588599527272">"如要返回,请使用三根手指在触控板上的任意位置左滑或右滑。"</string> + <!-- no translation found for touchpad_back_gesture_guidance (6263750214998421587) --> + <skip /> + <!-- no translation found for touchpad_back_gesture_finished (5353616006999726249) --> + <skip /> <string name="touchpad_back_gesture_animation_content_description" msgid="2646107450922379918">"触控板,其中显示了三根手指右移和左移"</string> <string name="touchpad_back_gesture_screen_animation_content_description" msgid="4036267494237748710">"设备屏幕,其中显示了返回手势的动画"</string> <string name="keyboard_backlight_dialog_title" msgid="8273102932345564724">"键盘背光"</string> @@ -1388,28 +1396,16 @@ <string name="home_controls_dream_label" msgid="6567105701292324257">"家居控制"</string> <string name="home_controls_dream_description" msgid="4644150952104035789">"通过屏保快速访问家居控制功能"</string> <string name="volume_undo_action" msgid="5815519725211877114">"撤消"</string> - <!-- no translation found for back_edu_toast_content (4530314597378982956) --> - <skip /> - <!-- no translation found for home_edu_toast_content (3381071147871955415) --> - <skip /> - <!-- no translation found for overview_edu_toast_content (5797030644017804518) --> - <skip /> - <!-- no translation found for all_apps_edu_toast_content (8807496014667211562) --> - <skip /> - <!-- no translation found for back_edu_notification_title (5624780717751357278) --> - <skip /> - <!-- no translation found for back_edu_notification_content (2497557451540954068) --> - <skip /> - <!-- no translation found for home_edu_notification_title (6097902076909654045) --> - <skip /> - <!-- no translation found for home_edu_notification_content (6631697734535766588) --> - <skip /> - <!-- no translation found for overview_edu_notification_title (1265824157319562406) --> - <skip /> - <!-- no translation found for overview_edu_notification_content (3578204677648432500) --> - <skip /> - <!-- no translation found for all_apps_edu_notification_title (372262997265569063) --> - <skip /> - <!-- no translation found for all_apps_edu_notification_content (3255070575694025585) --> - <skip /> + <string name="back_edu_toast_content" msgid="4530314597378982956">"如要返回,请用三根手指在触控板上向左或向右滑动"</string> + <string name="home_edu_toast_content" msgid="3381071147871955415">"如要前往主屏幕,请用三根手指在触控板上向上滑动"</string> + <string name="overview_edu_toast_content" msgid="5797030644017804518">"如要查看最近用过的应用,请用三根手指在触控板上向上滑动并按住"</string> + <string name="all_apps_edu_toast_content" msgid="8807496014667211562">"如要查看所有应用,请按下键盘上的快捷操作按键"</string> + <string name="back_edu_notification_title" msgid="5624780717751357278">"使用触控板返回"</string> + <string name="back_edu_notification_content" msgid="2497557451540954068">"用三根手指向左或向右滑动。点按即可了解更多手势。"</string> + <string name="home_edu_notification_title" msgid="6097902076909654045">"使用触控板前往主屏幕"</string> + <string name="home_edu_notification_content" msgid="6631697734535766588">"用三根手指向上滑动。点按即可了解更多手势。"</string> + <string name="overview_edu_notification_title" msgid="1265824157319562406">"使用触控板查看最近用过的应用"</string> + <string name="overview_edu_notification_content" msgid="3578204677648432500">"用三根手指向上滑动并按住。点按即可了解更多手势。"</string> + <string name="all_apps_edu_notification_title" msgid="372262997265569063">"使用键盘查看所有应用"</string> + <string name="all_apps_edu_notification_content" msgid="3255070575694025585">"您可随时按下快捷操作按键。点按即可了解更多手势。"</string> </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 e16e42a1f5cb..0446a1bc538b 100644 --- a/packages/SystemUI/res/values-zh-rCN/tiles_states_strings.xml +++ b/packages/SystemUI/res/values-zh-rCN/tiles_states_strings.xml @@ -56,11 +56,6 @@ <item msgid="5376619709702103243">"已关闭"</item> <item msgid="4875147066469902392">"已开启"</item> </string-array> - <string-array name="tile_states_modes"> - <item msgid="7764936419245199023">"不可用"</item> - <item msgid="2004750556637773692">"已关闭"</item> - <item msgid="8968530753931637871">"已开启"</item> - </string-array> <string-array name="tile_states_flashlight"> <item msgid="3465257127433353857">"不可用"</item> <item msgid="5044688398303285224">"已关闭"</item> diff --git a/packages/SystemUI/res/values-zh-rHK/strings.xml b/packages/SystemUI/res/values-zh-rHK/strings.xml index 7954e3552f8e..9c1049b041f6 100644 --- a/packages/SystemUI/res/values-zh-rHK/strings.xml +++ b/packages/SystemUI/res/values-zh-rHK/strings.xml @@ -388,6 +388,9 @@ <string name="performance" msgid="6552785217174378320">"效能"</string> <string name="user_interface" msgid="3712869377953950887">"使用者介面"</string> <string name="thermal" msgid="6758074791325414831">"熱能"</string> + <string name="custom" msgid="3337456985275158299">"自訂"</string> + <string name="custom_trace_settings_dialog_title" msgid="2608570500144830554">"自訂 Trace 設定"</string> + <string name="restore_default" msgid="5259420807486239755">"還原預設值"</string> <string name="quick_settings_onehanded_label" msgid="2416537930246274991">"單手模式"</string> <string name="quick_settings_hearing_devices_label" msgid="7277170419679404129">"助聽器"</string> <string name="quick_settings_hearing_devices_connected" msgid="6519069502397037781">"已連線"</string> @@ -429,9 +432,13 @@ <string name="zen_modes_dialog_title" msgid="4159138230418567383">"優先模式"</string> <string name="zen_modes_dialog_done" msgid="6654130880256438950">"完成"</string> <string name="zen_modes_dialog_settings" msgid="2310248023728936697">"設定"</string> - <!-- no translation found for zen_mode_on (9085304934016242591) --> + <string name="zen_mode_on" msgid="9085304934016242591">"開啟"</string> + <string name="zen_mode_off" msgid="1736604456618147306">"關閉"</string> + <!-- no translation found for zen_mode_set_up (7457957033034460064) --> <skip /> - <!-- no translation found for zen_mode_off (1736604456618147306) --> + <!-- no translation found for zen_mode_no_manual_invocation (1769975741344633672) --> + <skip /> + <!-- no translation found for zen_mode_active_modes (1625850411578488856) --> <skip /> <string name="zen_priority_introduction" msgid="3159291973383796646">"你不會受到聲音和震動騷擾 (鬧鐘、提醒、活動和你指定的來電者鈴聲除外)。當你選擇播放音樂、影片和遊戲等,仍可以聽到該內容的聲音。"</string> <string name="zen_alarms_introduction" msgid="3987266042682300470">"你不會受到聲音和震動騷擾 (鬧鐘除外)。當你選擇播放音樂、影片和遊戲等,仍可以聽到該內容的聲音。"</string> @@ -471,6 +478,8 @@ <string name="keyguard_indication_charging_time_slowly" msgid="301936949731705417">"<xliff:g id="PERCENTAGE">%2$s</xliff:g> • 慢速充電中 • <xliff:g id="CHARGING_TIME_LEFT">%1$s</xliff:g>後充滿電"</string> <string name="keyguard_indication_charging_time_dock" msgid="3149328898931741271">"<xliff:g id="PERCENTAGE">%2$s</xliff:g> • 充電中 • <xliff:g id="CHARGING_TIME_LEFT">%1$s</xliff:g>後充滿電"</string> <string name="accessibility_action_open_communal_hub" msgid="3081702792413787849">"上鎖畫面上的小工具"</string> + <!-- no translation found for accessibility_announcement_communal_widget_added (6911593106099328271) --> + <skip /> <string name="communal_tutorial_indicator_text" msgid="4503010353591430123">"向左滑動即可開始共用教學課程"</string> <string name="cta_tile_button_to_open_widget_editor" msgid="3871562362382963878">"自訂"</string> <string name="cta_tile_button_to_dismiss" msgid="3377597875997861754">"關閉"</string> @@ -499,8 +508,7 @@ <string name="accessibility_action_label_place_widget" msgid="1914197458644168978">"放置所選小工具"</string> <string name="communal_widget_picker_title" msgid="1953369090475731663">"上鎖畫面小工具"</string> <string name="communal_widget_picker_description" msgid="490515450110487871">"任何人都可查看上鎖畫面的小工具,即使平板電腦已上鎖亦然。"</string> - <!-- no translation found for accessibility_action_label_unselect_widget (1041811747619468698) --> - <skip /> + <string name="accessibility_action_label_unselect_widget" msgid="1041811747619468698">"取消揀小工具"</string> <string name="communal_widgets_disclaimer_title" msgid="1150954395585308868">"上鎖畫面小工具"</string> <string name="communal_widgets_disclaimer_text" msgid="1423545475160506349">"如要使用小工具開啟應用程式,系統會要求你驗證身分。請注意,即使平板電腦已鎖定,所有人還是能查看小工具。部分小工具可能不適用於上鎖畫面,而且新增至這裡後可能會有安全疑慮。"</string> <string name="communal_widgets_disclaimer_button" msgid="4423059765740780753">"知道了"</string> @@ -557,10 +565,8 @@ <string name="media_projection_action_text" msgid="3634906766918186440">"立即開始"</string> <string name="empty_shade_text" msgid="8935967157319717412">"沒有通知"</string> <string name="no_unseen_notif_text" msgid="395512586119868682">"沒有新通知"</string> - <!-- no translation found for adaptive_notification_edu_hun_title (7790738150177329960) --> - <skip /> - <!-- no translation found for adaptive_notification_edu_hun_text (7743367744129536610) --> - <skip /> + <string name="adaptive_notification_edu_hun_title" msgid="7790738150177329960">"調低通知強度功能已開啟"</string> + <string name="adaptive_notification_edu_hun_text" msgid="7743367744129536610">"如果同一時間收到太多通知,裝置會在最長 2 分鐘內調低音量,並減少警示。"</string> <string name="go_to_adaptive_notification_settings" msgid="2423690125178298479">"關閉"</string> <string name="unlock_to_see_notif_text" msgid="7439033907167561227">"解鎖即可查看舊通知"</string> <string name="quick_settings_disclosure_parental_controls" msgid="2114102871438223600">"此裝置由你的家長管理"</string> @@ -1226,7 +1232,6 @@ <string name="accessibility_fingerprint_bouncer" msgid="7189102492498735519">"需要驗證。掂一下指紋感應器就可以驗證。"</string> <string name="ongoing_phone_call_content_description" msgid="5332334388483099947">"通話中"</string> <string name="mobile_data_settings_title" msgid="3955246641380064901">"流動數據"</string> - <string name="preference_summary_default_combination" msgid="8453246369903749670">"<xliff:g id="STATE">%1$s</xliff:g>/<xliff:g id="NETWORKMODE">%2$s</xliff:g>"</string> <string name="mobile_data_connection_active" msgid="944490013299018227">"已連線"</string> <string name="mobile_data_temp_connection_active" msgid="4590222725908806824">"已暫時連線"</string> <string name="mobile_data_poor_connection" msgid="819617772268371434">"連線速度欠佳"</string> @@ -1380,7 +1385,10 @@ <string name="touchpad_tutorial_done_button" msgid="176168488821755503">"完成"</string> <string name="touchpad_tutorial_gesture_done" msgid="4784438360736821255">"太好了!"</string> <string name="touchpad_back_gesture_action_title" msgid="7199067250654332735">"返回"</string> - <string name="touchpad_back_gesture_guidance" msgid="4222430588599527272">"用三隻手指在觸控板上任何一處左右滑動即可返回。"</string> + <!-- no translation found for touchpad_back_gesture_guidance (6263750214998421587) --> + <skip /> + <!-- no translation found for touchpad_back_gesture_finished (5353616006999726249) --> + <skip /> <string name="touchpad_back_gesture_animation_content_description" msgid="2646107450922379918">"觸控板上有三隻手指左右移動"</string> <string name="touchpad_back_gesture_screen_animation_content_description" msgid="4036267494237748710">"裝置畫面顯示返回手勢動畫"</string> <string name="keyboard_backlight_dialog_title" msgid="8273102932345564724">"鍵盤背光"</string> @@ -1388,28 +1396,16 @@ <string name="home_controls_dream_label" msgid="6567105701292324257">"智能家居"</string> <string name="home_controls_dream_description" msgid="4644150952104035789">"在螢幕保護程式畫面上控制智能家居"</string> <string name="volume_undo_action" msgid="5815519725211877114">"復原"</string> - <!-- no translation found for back_edu_toast_content (4530314597378982956) --> - <skip /> - <!-- no translation found for home_edu_toast_content (3381071147871955415) --> - <skip /> - <!-- no translation found for overview_edu_toast_content (5797030644017804518) --> - <skip /> - <!-- no translation found for all_apps_edu_toast_content (8807496014667211562) --> - <skip /> - <!-- no translation found for back_edu_notification_title (5624780717751357278) --> - <skip /> - <!-- no translation found for back_edu_notification_content (2497557451540954068) --> - <skip /> - <!-- no translation found for home_edu_notification_title (6097902076909654045) --> - <skip /> - <!-- no translation found for home_edu_notification_content (6631697734535766588) --> - <skip /> - <!-- no translation found for overview_edu_notification_title (1265824157319562406) --> - <skip /> - <!-- no translation found for overview_edu_notification_content (3578204677648432500) --> - <skip /> - <!-- no translation found for all_apps_edu_notification_title (372262997265569063) --> - <skip /> - <!-- no translation found for all_apps_edu_notification_content (3255070575694025585) --> - <skip /> + <string name="back_edu_toast_content" msgid="4530314597378982956">"如要返回,請用三隻手指在觸控板上向左或向右滑動"</string> + <string name="home_edu_toast_content" msgid="3381071147871955415">"如要返回主畫面,請用三隻手指在觸控板上向上滑動"</string> + <string name="overview_edu_toast_content" msgid="5797030644017804518">"如要查看最近使用的應用程式,請用三隻手指在觸控板上向上滑動並按住"</string> + <string name="all_apps_edu_toast_content" msgid="8807496014667211562">"如要查看所有應用程式,請在鍵盤上按下快捷操作鍵"</string> + <string name="back_edu_notification_title" msgid="5624780717751357278">"使用觸控板返回"</string> + <string name="back_edu_notification_content" msgid="2497557451540954068">"用三隻手指向左或向右滑動。輕按即可瞭解更多手勢。"</string> + <string name="home_edu_notification_title" msgid="6097902076909654045">"使用觸控板返回主畫面"</string> + <string name="home_edu_notification_content" msgid="6631697734535766588">"用三隻手指向上滑動。輕按即可瞭解更多手勢。"</string> + <string name="overview_edu_notification_title" msgid="1265824157319562406">"使用觸控板查看最近使用的應用程式"</string> + <string name="overview_edu_notification_content" msgid="3578204677648432500">"用三隻手指向上滑動並按住。輕按即可瞭解更多手勢。"</string> + <string name="all_apps_edu_notification_title" msgid="372262997265569063">"使用鍵盤查看所有應用程式"</string> + <string name="all_apps_edu_notification_content" msgid="3255070575694025585">"隨時按下快捷操作鍵。輕按即可瞭解更多手勢。"</string> </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 57b4d2021585..cca7ac42906a 100644 --- a/packages/SystemUI/res/values-zh-rHK/tiles_states_strings.xml +++ b/packages/SystemUI/res/values-zh-rHK/tiles_states_strings.xml @@ -56,11 +56,6 @@ <item msgid="5376619709702103243">"已關閉"</item> <item msgid="4875147066469902392">"已開啟"</item> </string-array> - <string-array name="tile_states_modes"> - <item msgid="7764936419245199023">"無法使用"</item> - <item msgid="2004750556637773692">"關閉"</item> - <item msgid="8968530753931637871">"開啟"</item> - </string-array> <string-array name="tile_states_flashlight"> <item msgid="3465257127433353857">"無法使用"</item> <item msgid="5044688398303285224">"已關閉"</item> diff --git a/packages/SystemUI/res/values-zh-rTW/strings.xml b/packages/SystemUI/res/values-zh-rTW/strings.xml index b7043b59d980..1ac8ec4b69d9 100644 --- a/packages/SystemUI/res/values-zh-rTW/strings.xml +++ b/packages/SystemUI/res/values-zh-rTW/strings.xml @@ -388,6 +388,9 @@ <string name="performance" msgid="6552785217174378320">"效能"</string> <string name="user_interface" msgid="3712869377953950887">"使用者介面"</string> <string name="thermal" msgid="6758074791325414831">"熱成像"</string> + <string name="custom" msgid="3337456985275158299">"自訂"</string> + <string name="custom_trace_settings_dialog_title" msgid="2608570500144830554">"自訂追蹤記錄設定"</string> + <string name="restore_default" msgid="5259420807486239755">"還原為預設值"</string> <string name="quick_settings_onehanded_label" msgid="2416537930246274991">"單手模式"</string> <string name="quick_settings_hearing_devices_label" msgid="7277170419679404129">"助聽器"</string> <string name="quick_settings_hearing_devices_connected" msgid="6519069502397037781">"已連線"</string> @@ -429,9 +432,13 @@ <string name="zen_modes_dialog_title" msgid="4159138230418567383">"優先模式"</string> <string name="zen_modes_dialog_done" msgid="6654130880256438950">"完成"</string> <string name="zen_modes_dialog_settings" msgid="2310248023728936697">"設定"</string> - <!-- no translation found for zen_mode_on (9085304934016242591) --> + <string name="zen_mode_on" msgid="9085304934016242591">"開啟"</string> + <string name="zen_mode_off" msgid="1736604456618147306">"關閉"</string> + <!-- no translation found for zen_mode_set_up (7457957033034460064) --> <skip /> - <!-- no translation found for zen_mode_off (1736604456618147306) --> + <!-- no translation found for zen_mode_no_manual_invocation (1769975741344633672) --> + <skip /> + <!-- no translation found for zen_mode_active_modes (1625850411578488856) --> <skip /> <string name="zen_priority_introduction" msgid="3159291973383796646">"裝置不會發出音效或震動造成干擾,但是會保留與鬧鐘、提醒、活動和指定來電者有關的設定。如果你選擇播放音樂、影片和遊戲等內容,還是可以聽見相關音訊。"</string> <string name="zen_alarms_introduction" msgid="3987266042682300470">"裝置不會發出音效或震動造成干擾,但是會保留鬧鐘響鈴。如果你選擇播放音樂、影片和遊戲等內容,還是可以聽見相關音訊。"</string> @@ -471,6 +478,8 @@ <string name="keyguard_indication_charging_time_slowly" msgid="301936949731705417">"<xliff:g id="PERCENTAGE">%2$s</xliff:g> • 慢速充電中 • 將於 <xliff:g id="CHARGING_TIME_LEFT">%1$s</xliff:g>後充飽"</string> <string name="keyguard_indication_charging_time_dock" msgid="3149328898931741271">"<xliff:g id="PERCENTAGE">%2$s</xliff:g> • 充電中 • 將於 <xliff:g id="CHARGING_TIME_LEFT">%1$s</xliff:g>後充飽"</string> <string name="accessibility_action_open_communal_hub" msgid="3081702792413787849">"螢幕鎖定畫面上的小工具"</string> + <!-- no translation found for accessibility_announcement_communal_widget_added (6911593106099328271) --> + <skip /> <string name="communal_tutorial_indicator_text" msgid="4503010353591430123">"向左滑動即可啟動通用教學課程"</string> <string name="cta_tile_button_to_open_widget_editor" msgid="3871562362382963878">"自訂"</string> <string name="cta_tile_button_to_dismiss" msgid="3377597875997861754">"關閉"</string> @@ -499,8 +508,7 @@ <string name="accessibility_action_label_place_widget" msgid="1914197458644168978">"放置所選小工具"</string> <string name="communal_widget_picker_title" msgid="1953369090475731663">"螢幕鎖定畫面小工具"</string> <string name="communal_widget_picker_description" msgid="490515450110487871">"即使平板電腦已鎖定,所有人仍可查看螢幕鎖定畫面上的小工具。"</string> - <!-- no translation found for accessibility_action_label_unselect_widget (1041811747619468698) --> - <skip /> + <string name="accessibility_action_label_unselect_widget" msgid="1041811747619468698">"取消選取小工具"</string> <string name="communal_widgets_disclaimer_title" msgid="1150954395585308868">"螢幕鎖定小工具"</string> <string name="communal_widgets_disclaimer_text" msgid="1423545475160506349">"如要使用小工具開啟應用程式,系統會要求你驗證身分。請注意,即使平板電腦已鎖定,所有人還是能查看小工具。某些小工具可能不適用於螢幕鎖定畫面,而且新增到這裡可能有安全疑慮。"</string> <string name="communal_widgets_disclaimer_button" msgid="4423059765740780753">"我知道了"</string> @@ -557,10 +565,8 @@ <string name="media_projection_action_text" msgid="3634906766918186440">"立即開始"</string> <string name="empty_shade_text" msgid="8935967157319717412">"沒有通知"</string> <string name="no_unseen_notif_text" msgid="395512586119868682">"沒有新通知"</string> - <!-- no translation found for adaptive_notification_edu_hun_title (7790738150177329960) --> - <skip /> - <!-- no translation found for adaptive_notification_edu_hun_text (7743367744129536610) --> - <skip /> + <string name="adaptive_notification_edu_hun_title" msgid="7790738150177329960">"通知緩和設定已開啟"</string> + <string name="adaptive_notification_edu_hun_text" msgid="7743367744129536610">"如果一次收到過多通知,裝置就會自動降低音量並減少通知數量,持續時間最多 2 分鐘。"</string> <string name="go_to_adaptive_notification_settings" msgid="2423690125178298479">"關閉"</string> <string name="unlock_to_see_notif_text" msgid="7439033907167561227">"解鎖即可查看舊通知"</string> <string name="quick_settings_disclosure_parental_controls" msgid="2114102871438223600">"這個裝置是由你的家長管理"</string> @@ -1226,7 +1232,6 @@ <string name="accessibility_fingerprint_bouncer" msgid="7189102492498735519">"需要驗證。輕觸指紋感應器即可進行驗證。"</string> <string name="ongoing_phone_call_content_description" msgid="5332334388483099947">"通話中"</string> <string name="mobile_data_settings_title" msgid="3955246641380064901">"行動數據"</string> - <string name="preference_summary_default_combination" msgid="8453246369903749670">"<xliff:g id="STATE">%1$s</xliff:g>/<xliff:g id="NETWORKMODE">%2$s</xliff:g>"</string> <string name="mobile_data_connection_active" msgid="944490013299018227">"已連線"</string> <string name="mobile_data_temp_connection_active" msgid="4590222725908806824">"已暫時建立連線"</string> <string name="mobile_data_poor_connection" msgid="819617772268371434">"連線品質不佳"</string> @@ -1380,7 +1385,10 @@ <string name="touchpad_tutorial_done_button" msgid="176168488821755503">"完成"</string> <string name="touchpad_tutorial_gesture_done" msgid="4784438360736821255">"太棒了!"</string> <string name="touchpad_back_gesture_action_title" msgid="7199067250654332735">"返回"</string> - <string name="touchpad_back_gesture_guidance" msgid="4222430588599527272">"如要返回,請用三指在觸控板上向左或右滑動。"</string> + <!-- no translation found for touchpad_back_gesture_guidance (6263750214998421587) --> + <skip /> + <!-- no translation found for touchpad_back_gesture_finished (5353616006999726249) --> + <skip /> <string name="touchpad_back_gesture_animation_content_description" msgid="2646107450922379918">"動畫顯示三指正在觸控板上向左右移動"</string> <string name="touchpad_back_gesture_screen_animation_content_description" msgid="4036267494237748710">"裝置畫面顯示返回手勢的動畫"</string> <string name="keyboard_backlight_dialog_title" msgid="8273102932345564724">"鍵盤背光"</string> @@ -1388,28 +1396,16 @@ <string name="home_controls_dream_label" msgid="6567105701292324257">"居家控制"</string> <string name="home_controls_dream_description" msgid="4644150952104035789">"在螢幕保護程式畫面上快速存取居家控制功能"</string> <string name="volume_undo_action" msgid="5815519725211877114">"復原"</string> - <!-- no translation found for back_edu_toast_content (4530314597378982956) --> - <skip /> - <!-- no translation found for home_edu_toast_content (3381071147871955415) --> - <skip /> - <!-- no translation found for overview_edu_toast_content (5797030644017804518) --> - <skip /> - <!-- no translation found for all_apps_edu_toast_content (8807496014667211562) --> - <skip /> - <!-- no translation found for back_edu_notification_title (5624780717751357278) --> - <skip /> - <!-- no translation found for back_edu_notification_content (2497557451540954068) --> - <skip /> - <!-- no translation found for home_edu_notification_title (6097902076909654045) --> - <skip /> - <!-- no translation found for home_edu_notification_content (6631697734535766588) --> - <skip /> - <!-- no translation found for overview_edu_notification_title (1265824157319562406) --> - <skip /> - <!-- no translation found for overview_edu_notification_content (3578204677648432500) --> - <skip /> - <!-- no translation found for all_apps_edu_notification_title (372262997265569063) --> - <skip /> - <!-- no translation found for all_apps_edu_notification_content (3255070575694025585) --> - <skip /> + <string name="back_edu_toast_content" msgid="4530314597378982956">"如要返回,請在觸控板上用三指向左或向右滑動"</string> + <string name="home_edu_toast_content" msgid="3381071147871955415">"如要前往主畫面,請在觸控板上用三指向上滑動"</string> + <string name="overview_edu_toast_content" msgid="5797030644017804518">"如要查看最近使用的應用程式,請在觸控板上向上滑動並按住"</string> + <string name="all_apps_edu_toast_content" msgid="8807496014667211562">"如要查看所有應用程式,請按下鍵盤上的快捷操作鍵"</string> + <string name="back_edu_notification_title" msgid="5624780717751357278">"使用觸控板返回"</string> + <string name="back_edu_notification_content" msgid="2497557451540954068">"用三指向左或向右滑動。輕觸即可進一步瞭解手勢。"</string> + <string name="home_edu_notification_title" msgid="6097902076909654045">"使用觸控板前往主畫面"</string> + <string name="home_edu_notification_content" msgid="6631697734535766588">"用三指向上滑動。輕觸即可進一步瞭解手勢。"</string> + <string name="overview_edu_notification_title" msgid="1265824157319562406">"使用觸控板查看最近使用的應用程式"</string> + <string name="overview_edu_notification_content" msgid="3578204677648432500">"用三指向上滑動並按住。輕觸即可進一步瞭解手勢。"</string> + <string name="all_apps_edu_notification_title" msgid="372262997265569063">"使用鍵盤查看所有應用程式"</string> + <string name="all_apps_edu_notification_content" msgid="3255070575694025585">"你隨時可以按下快捷操作鍵。輕觸即可進一步瞭解手勢。"</string> </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 3a64fddc44c9..4cc580434a36 100644 --- a/packages/SystemUI/res/values-zh-rTW/tiles_states_strings.xml +++ b/packages/SystemUI/res/values-zh-rTW/tiles_states_strings.xml @@ -56,11 +56,6 @@ <item msgid="5376619709702103243">"已關閉"</item> <item msgid="4875147066469902392">"已開啟"</item> </string-array> - <string-array name="tile_states_modes"> - <item msgid="7764936419245199023">"無法使用"</item> - <item msgid="2004750556637773692">"已關閉"</item> - <item msgid="8968530753931637871">"已開啟"</item> - </string-array> <string-array name="tile_states_flashlight"> <item msgid="3465257127433353857">"無法使用"</item> <item msgid="5044688398303285224">"已關閉"</item> diff --git a/packages/SystemUI/res/values-zu/strings.xml b/packages/SystemUI/res/values-zu/strings.xml index 436c7c6a3757..3a34c47385d7 100644 --- a/packages/SystemUI/res/values-zu/strings.xml +++ b/packages/SystemUI/res/values-zu/strings.xml @@ -388,6 +388,9 @@ <string name="performance" msgid="6552785217174378320">"Ukusebenza"</string> <string name="user_interface" msgid="3712869377953950887">"Okusetshenziswa Kubonwa"</string> <string name="thermal" msgid="6758074791325414831">"Ithermal"</string> + <string name="custom" msgid="3337456985275158299">"Okumuntu ngamunye"</string> + <string name="custom_trace_settings_dialog_title" msgid="2608570500144830554">"Amasethingi Okulandelela Okomuntu Ngamunye"</string> + <string name="restore_default" msgid="5259420807486239755">"Buyisela Okuzenzakalelayo"</string> <string name="quick_settings_onehanded_label" msgid="2416537930246274991">"Imodi yesandla esisodwa"</string> <string name="quick_settings_hearing_devices_label" msgid="7277170419679404129">"Izinsizakuzwa"</string> <string name="quick_settings_hearing_devices_connected" msgid="6519069502397037781">"Kuyasebenza"</string> @@ -429,9 +432,13 @@ <string name="zen_modes_dialog_title" msgid="4159138230418567383">"Amamodi okubalulekile"</string> <string name="zen_modes_dialog_done" msgid="6654130880256438950">"Kwenziwe"</string> <string name="zen_modes_dialog_settings" msgid="2310248023728936697">"Amasethingi"</string> - <!-- no translation found for zen_mode_on (9085304934016242591) --> + <string name="zen_mode_on" msgid="9085304934016242591">"Vuliwe"</string> + <string name="zen_mode_off" msgid="1736604456618147306">"Valiwe"</string> + <!-- no translation found for zen_mode_set_up (7457957033034460064) --> <skip /> - <!-- no translation found for zen_mode_off (1736604456618147306) --> + <!-- no translation found for zen_mode_no_manual_invocation (1769975741344633672) --> + <skip /> + <!-- no translation found for zen_mode_active_modes (1625850411578488856) --> <skip /> <string name="zen_priority_introduction" msgid="3159291973383796646">"Ngeke uphazanyiswe imisindo nokudlidliza, ngaphandle kusukela kuma-alamu, izikhumbuzi, imicimbi, nabafonayo obacacisayo. Usazozwa noma yini okhetha ukuyidlala okufaka umculo, amavidiyo, namageyimu."</string> <string name="zen_alarms_introduction" msgid="3987266042682300470">"Ngeke uze uphazanyiswe imisindo nokudlidliza, ngaphandle kusukela kuma-alamu. Usazozwa noma yini okhetha ukuyidlala okufaka umculo, amavidiyo, namageyimu."</string> @@ -471,6 +478,8 @@ <string name="keyguard_indication_charging_time_slowly" msgid="301936949731705417">"<xliff:g id="PERCENTAGE">%2$s</xliff:g> • Ishaja kancane • Izogcwala ngo-<xliff:g id="CHARGING_TIME_LEFT">%1$s</xliff:g>"</string> <string name="keyguard_indication_charging_time_dock" msgid="3149328898931741271">"<xliff:g id="PERCENTAGE">%2$s</xliff:g> • Iyashaja • Izogcwala ngo-<xliff:g id="CHARGING_TIME_LEFT">%1$s</xliff:g>"</string> <string name="accessibility_action_open_communal_hub" msgid="3081702792413787849">"Amawijethi ekukhiyeni isikrini"</string> + <!-- no translation found for accessibility_announcement_communal_widget_added (6911593106099328271) --> + <skip /> <string name="communal_tutorial_indicator_text" msgid="4503010353591430123">"Swayiphela kwesokunxele ukuze uqale okokufundisa komphakathi"</string> <string name="cta_tile_button_to_open_widget_editor" msgid="3871562362382963878">"Enza ngendlela oyifisayo"</string> <string name="cta_tile_button_to_dismiss" msgid="3377597875997861754">"Chitha"</string> @@ -499,8 +508,7 @@ <string name="accessibility_action_label_place_widget" msgid="1914197458644168978">"beka iwijethi ekhethiwe"</string> <string name="communal_widget_picker_title" msgid="1953369090475731663">"Amawijethi wesikrini esikhiyiwe"</string> <string name="communal_widget_picker_description" msgid="490515450110487871">"Noma ubani angabuka amawijethi ngisho noma ithebulethi ikhiyiwe."</string> - <!-- no translation found for accessibility_action_label_unselect_widget (1041811747619468698) --> - <skip /> + <string name="accessibility_action_label_unselect_widget" msgid="1041811747619468698">"yeka ukukhetha iwijethi"</string> <string name="communal_widgets_disclaimer_title" msgid="1150954395585308868">"Amawijethi wesikrini esikhiyiwe"</string> <string name="communal_widgets_disclaimer_text" msgid="1423545475160506349">"Ukuze uvule i-app usebenzisa iwijethi, uzodinga ukuqinisekisa ukuthi nguwe. Futhi, khumbula ukuthi noma ubani angakwazi ukuzibuka, nanoma ithebhulethi yakho ikhiyiwe. Amanye amawijethi kungenzeka abengahloselwe ukukhiya isikrini sakho futhi kungenzeka awaphephile ukuthi angafakwa lapha."</string> <string name="communal_widgets_disclaimer_button" msgid="4423059765740780753">"Ngiyezwa"</string> @@ -557,10 +565,8 @@ <string name="media_projection_action_text" msgid="3634906766918186440">"Qala manje"</string> <string name="empty_shade_text" msgid="8935967157319717412">"Azikho izaziso"</string> <string name="no_unseen_notif_text" msgid="395512586119868682">"Azikho izaziso ezintsha"</string> - <!-- no translation found for adaptive_notification_edu_hun_title (7790738150177329960) --> - <skip /> - <!-- no translation found for adaptive_notification_edu_hun_text (7743367744129536610) --> - <skip /> + <string name="adaptive_notification_edu_hun_title" msgid="7790738150177329960">"Ukwehlisa umsindo wezaziso kuvuliwe"</string> + <string name="adaptive_notification_edu_hun_text" msgid="7743367744129536610">"Ivolumu yedivayisi yakho kanye nezexwayiso kuncishiswa ngokuzenzakalelayo imizuzu efika kwemi-2 lapho uthola izaziso eziningi kakhulu ngesikhathi esisodwa."</string> <string name="go_to_adaptive_notification_settings" msgid="2423690125178298479">"Vala"</string> <string name="unlock_to_see_notif_text" msgid="7439033907167561227">"Vula ukuze ubone izaziso ezindala"</string> <string name="quick_settings_disclosure_parental_controls" msgid="2114102871438223600">"Le divayisi iphethwe ngumzali wakho"</string> @@ -1226,7 +1232,6 @@ <string name="accessibility_fingerprint_bouncer" msgid="7189102492498735519">"Ukufakazela ubuqiniso budingekile. Thinta inzwa yezigxivizo zeminwe ukuze uqinisekise."</string> <string name="ongoing_phone_call_content_description" msgid="5332334388483099947">"Ikholi yefoni eqhubekayo"</string> <string name="mobile_data_settings_title" msgid="3955246641380064901">"Idatha yeselula"</string> - <string name="preference_summary_default_combination" msgid="8453246369903749670">"<xliff:g id="STATE">%1$s</xliff:g> / <xliff:g id="NETWORKMODE">%2$s</xliff:g>"</string> <string name="mobile_data_connection_active" msgid="944490013299018227">"Ixhunyiwe"</string> <string name="mobile_data_temp_connection_active" msgid="4590222725908806824">"Ixhume okwesikhashana"</string> <string name="mobile_data_poor_connection" msgid="819617772268371434">"Uxhumo olungeluhle"</string> @@ -1380,7 +1385,10 @@ <string name="touchpad_tutorial_done_button" msgid="176168488821755503">"Kwenziwe"</string> <string name="touchpad_tutorial_gesture_done" msgid="4784438360736821255">"Umsebenzi omuhle!"</string> <string name="touchpad_back_gesture_action_title" msgid="7199067250654332735">"Buyela emuva"</string> - <string name="touchpad_back_gesture_guidance" msgid="4222430588599527272">"Ukuze ubuyele emuva, swayiphela kwesokunxele noma kwesokudla usebenzisa iminwe emithathu noma yikuphi ephedini yokuthinta."</string> + <!-- no translation found for touchpad_back_gesture_guidance (6263750214998421587) --> + <skip /> + <!-- no translation found for touchpad_back_gesture_finished (5353616006999726249) --> + <skip /> <string name="touchpad_back_gesture_animation_content_description" msgid="2646107450922379918">"Iphedi yokuthinta ebonisa iminwe emithathu iya kwesokudla nakwesokunxele"</string> <string name="touchpad_back_gesture_screen_animation_content_description" msgid="4036267494237748710">"Isikrini sedivayisi esibonisa opopayi bokuthinta kwasemuva"</string> <string name="keyboard_backlight_dialog_title" msgid="8273102932345564724">"Ilambu lekhibhodi"</string> @@ -1388,28 +1396,16 @@ <string name="home_controls_dream_label" msgid="6567105701292324257">"Izilawuli Zasekhaya"</string> <string name="home_controls_dream_description" msgid="4644150952104035789">"Finyelela ngokushesha izilawuli zakho zasekhaya njengesigcini-skrini"</string> <string name="volume_undo_action" msgid="5815519725211877114">"Hlehlisa"</string> - <!-- no translation found for back_edu_toast_content (4530314597378982956) --> - <skip /> - <!-- no translation found for home_edu_toast_content (3381071147871955415) --> - <skip /> - <!-- no translation found for overview_edu_toast_content (5797030644017804518) --> - <skip /> - <!-- no translation found for all_apps_edu_toast_content (8807496014667211562) --> - <skip /> - <!-- no translation found for back_edu_notification_title (5624780717751357278) --> - <skip /> - <!-- no translation found for back_edu_notification_content (2497557451540954068) --> - <skip /> - <!-- no translation found for home_edu_notification_title (6097902076909654045) --> - <skip /> - <!-- no translation found for home_edu_notification_content (6631697734535766588) --> - <skip /> - <!-- no translation found for overview_edu_notification_title (1265824157319562406) --> - <skip /> - <!-- no translation found for overview_edu_notification_content (3578204677648432500) --> - <skip /> - <!-- no translation found for all_apps_edu_notification_title (372262997265569063) --> - <skip /> - <!-- no translation found for all_apps_edu_notification_content (3255070575694025585) --> - <skip /> + <string name="back_edu_toast_content" msgid="4530314597378982956">"Ukuze ubuyele emuva, swayiphela kwesokunxele noma kwesokudla ngeminwe emithathu ephedini yokuthinta"</string> + <string name="home_edu_toast_content" msgid="3381071147871955415">"Ukuze uye ekhaya, swayiphela phezulu ngeminwe emithathu ephedini yokuthinta"</string> + <string name="overview_edu_toast_content" msgid="5797030644017804518">"Ukuze ubuke ama-app akamuva, swayiphela phezulu bese ubambe ngeminwe emithathu ephedini yokuthinta"</string> + <string name="all_apps_edu_toast_content" msgid="8807496014667211562">"Ukuze ubuke wonke ama-app wakho, cindezela inkinobho yokufinyelela kukhibhodi yakho"</string> + <string name="back_edu_notification_title" msgid="5624780717751357278">"Sebenzisa iphedi yokuthinta ukuze ubuyele emuva"</string> + <string name="back_edu_notification_content" msgid="2497557451540954068">"Swayiphela kwesokunxele noma kwesokudla usebenzisa iminwe emithathu. Thepha ukuze ufunde kabanzi ngokunyakazisa umzimba."</string> + <string name="home_edu_notification_title" msgid="6097902076909654045">"Sebenzisa iphedi yokuthinta ukuya ekhaya"</string> + <string name="home_edu_notification_content" msgid="6631697734535766588">"Swayiphela phezulu usebenzisa iminwe emithathu. Thepha ukuze ufunde kabanzi ngokunyakazisa umzimba."</string> + <string name="overview_edu_notification_title" msgid="1265824157319562406">"Sebenzisa iphedi yokuthinta ukuze ubuke ama-app akamuva"</string> + <string name="overview_edu_notification_content" msgid="3578204677648432500">"Swayiphela phezulu bese uyabamba usebenzisa iminwe emithathu. Thepha ukuze ufunde kabanzi ngokunyakazisa umzimba."</string> + <string name="all_apps_edu_notification_title" msgid="372262997265569063">"Sebenzisa ikhibhodi yakho ukubuka wonke ama-app"</string> + <string name="all_apps_edu_notification_content" msgid="3255070575694025585">"Cindezela inkinobho yokufinyelela noma kunini. Thepha ukuze ufunde kabanzi ngokunyakazisa umzimba."</string> </resources> diff --git a/packages/SystemUI/res/values-zu/tiles_states_strings.xml b/packages/SystemUI/res/values-zu/tiles_states_strings.xml index 4cd138dfafbe..a795ee8b9d75 100644 --- a/packages/SystemUI/res/values-zu/tiles_states_strings.xml +++ b/packages/SystemUI/res/values-zu/tiles_states_strings.xml @@ -56,11 +56,6 @@ <item msgid="5376619709702103243">"Valiwe"</item> <item msgid="4875147066469902392">"Vuliwe"</item> </string-array> - <string-array name="tile_states_modes"> - <item msgid="7764936419245199023">"Ayitholakali"</item> - <item msgid="2004750556637773692">"Ivaliwe"</item> - <item msgid="8968530753931637871">"Ivuliwe"</item> - </string-array> <string-array name="tile_states_flashlight"> <item msgid="3465257127433353857">"Akutholakali"</item> <item msgid="5044688398303285224">"Valiwe"</item> diff --git a/packages/SystemUI/res/values/config.xml b/packages/SystemUI/res/values/config.xml index 30f23bfc9753..c29c2369a9d4 100644 --- a/packages/SystemUI/res/values/config.xml +++ b/packages/SystemUI/res/values/config.xml @@ -104,7 +104,7 @@ <!-- Tiles native to System UI. Order should match "quick_settings_tiles_default" --> <string name="quick_settings_tiles_stock" translatable="false"> - internet,bt,flashlight,dnd,modes,alarm,airplane,controls,wallet,rotation,battery,cast,screenrecord,mictoggle,cameratoggle,location,hotspot,inversion,saver,dark,work,night,reverse,reduce_brightness,qr_code_scanner,onehanded,color_correction,dream,font_scaling,record_issue,hearing_devices + internet,bt,flashlight,dnd,alarm,airplane,controls,wallet,rotation,battery,cast,screenrecord,mictoggle,cameratoggle,location,hotspot,inversion,saver,dark,work,night,reverse,reduce_brightness,qr_code_scanner,onehanded,color_correction,dream,font_scaling,record_issue,hearing_devices </string> <!-- The tiles to display in QuickSettings --> diff --git a/packages/SystemUI/res/values/strings.xml b/packages/SystemUI/res/values/strings.xml index e56b638bdb95..e590f15d27c2 100644 --- a/packages/SystemUI/res/values/strings.xml +++ b/packages/SystemUI/res/values/strings.xml @@ -1109,6 +1109,14 @@ <!-- Priority modes: label for a mode that cannot be manually turned on [CHAR LIMIT=35] --> <string name="zen_mode_no_manual_invocation">Manage in settings</string> + <string name="zen_mode_active_modes"> + {count, plural, + =0 {No active modes} + =1 {{mode} is active} + other {# modes are active} + } + </string> + <!-- Zen mode: Priority only introduction message on first use --> <string name="zen_priority_introduction">You won\'t be disturbed by sounds and vibrations, except from alarms, reminders, events, and callers you specify. You\'ll still hear anything you choose to play including music, videos, and games.</string> @@ -1217,6 +1225,9 @@ <!-- Label for accessibility action that shows widgets on lock screen on click. [CHAR LIMIT=NONE] --> <string name="accessibility_action_open_communal_hub">Widgets on lock screen</string> + <!-- Label for an accessibility announcement when a widget has been added to the lock screen. [CHAR LIMIT=NONE] --> + <string name="accessibility_announcement_communal_widget_added"><xliff:g id="widget_name" example="Calendar month view">%1$s</xliff:g> widget added to lock screen</string> + <!-- Indicator on keyguard to start the communal tutorial. [CHAR LIMIT=100] --> <string name="communal_tutorial_indicator_text">Swipe left to start the communal tutorial</string> @@ -3214,9 +3225,6 @@ <!-- Provider Model: Default title of the mobile network in the mobile layout. [CHAR LIMIT=50] --> <string name="mobile_data_settings_title">Mobile data</string> - <!-- Provider Model: Summary text separator for preferences including a short description - (eg. "Connected / 5G"). [CHAR LIMIT=50] --> - <string name="preference_summary_default_combination"><xliff:g id="state" example="Connected">%1$s</xliff:g> / <xliff:g id="networkMode" example="LTE">%2$s</xliff:g></string> <!-- Provider Model: Summary indicating that a SIM has an active mobile data connection [CHAR LIMIT=50] --> <string name="mobile_data_connection_active">Connected</string> @@ -3673,7 +3681,10 @@ <!-- Touchpad back gesture action name in tutorial [CHAR LIMIT=NONE] --> <string name="touchpad_back_gesture_action_title">Go back</string> <!-- Touchpad back gesture guidance in gestures tutorial [CHAR LIMIT=NONE] --> - <string name="touchpad_back_gesture_guidance">To go back, swipe left or right using three fingers anywhere on the touchpad.</string> + <string name="touchpad_back_gesture_guidance">To go back, swipe left or right using three fingers anywhere on the touchpad.\n\nYou can also use the keyboard shortcut +Action + ESC for this.</string> + <!-- Text shown to the user after they complete back gesture tutorial [CHAR LIMIT=NONE] --> + <string name="touchpad_back_gesture_finished">You completed the go back gesture.</string> <string name="touchpad_back_gesture_animation_content_description">Touchpad showing three fingers moving right and left</string> <string name="touchpad_back_gesture_screen_animation_content_description">Device screen showing animation for back gesture</string> @@ -3714,4 +3725,16 @@ <string name="all_apps_edu_notification_title">Use your keyboard to view all apps</string> <!-- Education notification text for All Apps [CHAR_LIMIT=100] --> <string name="all_apps_edu_notification_content">Press the action key at any time. Tap to learn more gestures.</string> + + <!-- Title for Extra Dim dialog [CHAR LIMIT=NONE] --> + <string name="accessibility_deprecate_extra_dim_dialog_title">Extra dim is now part of the brightness bar</string> + <!-- Content description for Extra Dim dialog. This helps users understand that we could make screen much dimmer by lowering the brightness through the brightness bar in a dark environment. [CHAR LIMIT=NONE] --> + <string name="accessibility_deprecate_extra_dim_dialog_description"> + You can now make the screen extra dim by lowering the brightness level even further from the top of your screen.\n\nThis works best when you\'re in a dark environment. + </string> + <!-- Label for button removing Extra Dim shortcuts [CHAR LIMIT=NONE] --> + <string name="accessibility_deprecate_extra_dim_dialog_button">Remove extra dim shortcut</string> + <!-- Toast message for notifying users to use regular brightness bar to lower the brightness. [CHAR LIMIT=NONE] --> + <string name="accessibility_deprecate_extra_dim_dialog_toast"> + Extra dim shortcut removed. To lower your brightness, use the regular brightness bar.</string> </resources> diff --git a/packages/SystemUI/res/values/tiles_states_strings.xml b/packages/SystemUI/res/values/tiles_states_strings.xml index c7029272db7d..ad09b466dd3e 100644 --- a/packages/SystemUI/res/values/tiles_states_strings.xml +++ b/packages/SystemUI/res/values/tiles_states_strings.xml @@ -85,16 +85,6 @@ <item>On</item> </string-array> - <!-- State names for modes (Priority modes) tile: unavailable, off, on. - This subtitle is shown when the tile is in that particular state but does not set its own - subtitle, so some of these may never appear on screen. They should still be translated as - if they could appear. [CHAR LIMIT=32] --> - <string-array name="tile_states_modes"> - <item>Unavailable</item> - <item>Off</item> - <item>On</item> - </string-array> - <!-- State names for flashlight tile: unavailable, off, on. This subtitle is shown when the tile is in that particular state but does not set its own subtitle, so some of these may never appear on screen. They should still be translated as diff --git a/packages/SystemUI/src/com/android/keyguard/KeyguardSecurityContainerController.java b/packages/SystemUI/src/com/android/keyguard/KeyguardSecurityContainerController.java index 428cd0e7da0a..93ee179c5b63 100644 --- a/packages/SystemUI/src/com/android/keyguard/KeyguardSecurityContainerController.java +++ b/packages/SystemUI/src/com/android/keyguard/KeyguardSecurityContainerController.java @@ -724,7 +724,10 @@ public class KeyguardSecurityContainerController extends ViewController<Keyguard @Override public void onResume(int reason) { if (DEBUG) Log.d(TAG, "screen on, instance " + Integer.toHexString(hashCode())); + mView.clearFocus(); + mView.clearAccessibilityFocus(); mView.requestFocus(); + mView.requestAccessibilityFocus(); if (mCurrentSecurityMode != SecurityMode.None) { int state = SysUiStatsLog.KEYGUARD_BOUNCER_STATE_CHANGED__STATE__SHOWN; if (mView.isSidedSecurityMode()) { diff --git a/packages/SystemUI/src/com/android/keyguard/KeyguardUpdateMonitor.java b/packages/SystemUI/src/com/android/keyguard/KeyguardUpdateMonitor.java index 7f5839d4f1fb..0da252da5cc9 100644 --- a/packages/SystemUI/src/com/android/keyguard/KeyguardUpdateMonitor.java +++ b/packages/SystemUI/src/com/android/keyguard/KeyguardUpdateMonitor.java @@ -2086,6 +2086,7 @@ public class KeyguardUpdateMonitor implements TrustManager.TrustListener, Dumpab private void handleUserUnlocked(int userId) { Assert.isMainThread(); + mLogger.logUserUnlocked(userId); mUserIsUnlocked.put(userId, true); mNeedsSlowUnlockTransition = resolveNeedsSlowUnlockTransition(); for (int i = 0; i < mCallbacks.size(); i++) { @@ -2098,12 +2099,15 @@ public class KeyguardUpdateMonitor implements TrustManager.TrustListener, Dumpab private void handleUserStopped(int userId) { Assert.isMainThread(); - mUserIsUnlocked.put(userId, mUserManager.isUserUnlocked(userId)); + boolean isUnlocked = mUserManager.isUserUnlocked(userId); + mLogger.logUserStopped(userId, isUnlocked); + mUserIsUnlocked.put(userId, isUnlocked); } @VisibleForTesting void handleUserRemoved(int userId) { Assert.isMainThread(); + mLogger.logUserRemoved(userId); mUserIsUnlocked.delete(userId); mUserTrustIsUsuallyManaged.delete(userId); } @@ -2444,7 +2448,9 @@ public class KeyguardUpdateMonitor implements TrustManager.TrustListener, Dumpab mTaskStackChangeListeners.registerTaskStackListener(mTaskStackListener); int user = mSelectedUserInteractor.getSelectedUserId(true); - mUserIsUnlocked.put(user, mUserManager.isUserUnlocked(user)); + boolean isUserUnlocked = mUserManager.isUserUnlocked(user); + mLogger.logUserUnlockedInitialState(user, isUserUnlocked); + mUserIsUnlocked.put(user, isUserUnlocked); mLogoutEnabled = mDevicePolicyManager.isLogoutEnabled(); updateSecondaryLockscreenRequirement(user); List<UserInfo> allUsers = mUserManager.getUsers(); @@ -4059,6 +4065,9 @@ public class KeyguardUpdateMonitor implements TrustManager.TrustListener, Dumpab pw.println(" strongAuthFlags=" + Integer.toHexString(strongAuthFlags)); pw.println("ActiveUnlockRunning=" + mTrustManager.isActiveUnlockRunning(mSelectedUserInteractor.getSelectedUserId())); + pw.println("userUnlockedCache[userid=" + userId + "]=" + isUserUnlocked(userId)); + pw.println("actualUserUnlocked[userid=" + userId + "]=" + + mUserManager.isUserUnlocked(userId)); new DumpsysTableLogger( "KeyguardActiveUnlockTriggers", KeyguardActiveUnlockModel.TABLE_HEADERS, diff --git a/packages/SystemUI/src/com/android/keyguard/logging/KeyguardUpdateMonitorLogger.kt b/packages/SystemUI/src/com/android/keyguard/logging/KeyguardUpdateMonitorLogger.kt index 1f4e732c21e4..0b58f06e0d5d 100644 --- a/packages/SystemUI/src/com/android/keyguard/logging/KeyguardUpdateMonitorLogger.kt +++ b/packages/SystemUI/src/com/android/keyguard/logging/KeyguardUpdateMonitorLogger.kt @@ -391,6 +391,7 @@ constructor(@KeyguardUpdateMonitorLog private val logBuffer: LogBuffer) { { "handleTimeFormatUpdate timeFormat=$str1" } ) } + fun logUdfpsPointerDown(sensorId: Int) { logBuffer.log(TAG, DEBUG, { int1 = sensorId }, { "onUdfpsPointerDown, sensorId: $int1" }) } @@ -639,12 +640,45 @@ constructor(@KeyguardUpdateMonitorLog private val logBuffer: LogBuffer) { { "fingerprint acquire message: $int1" } ) } + fun logForceIsDismissibleKeyguard(keepUnlocked: Boolean) { logBuffer.log( - TAG, - DEBUG, - { bool1 = keepUnlocked }, - { "keepUnlockedOnFold changed to: $bool1" } + TAG, + DEBUG, + { bool1 = keepUnlocked }, + { "keepUnlockedOnFold changed to: $bool1" } + ) + } + + fun logUserUnlocked(userId: Int) { + logBuffer.log(TAG, DEBUG, { int1 = userId }, { "userUnlocked userId: $int1" }) + } + + fun logUserStopped(userId: Int, isUnlocked: Boolean) { + logBuffer.log( + TAG, + DEBUG, + { + int1 = userId + bool1 = isUnlocked + }, + { "userStopped userId: $int1 isUnlocked: $bool1" } + ) + } + + fun logUserRemoved(userId: Int) { + logBuffer.log(TAG, DEBUG, { int1 = userId }, { "userRemoved userId: $int1" }) + } + + fun logUserUnlockedInitialState(userId: Int, isUnlocked: Boolean) { + logBuffer.log( + TAG, + DEBUG, + { + int1 = userId + bool1 = isUnlocked + }, + { "userUnlockedInitialState userId: $int1 isUnlocked: $bool1" } ) } } diff --git a/packages/SystemUI/src/com/android/systemui/accessibility/FullscreenMagnificationController.java b/packages/SystemUI/src/com/android/systemui/accessibility/FullscreenMagnificationController.java index 3c0ac9a172f9..394f8dd629ae 100644 --- a/packages/SystemUI/src/com/android/systemui/accessibility/FullscreenMagnificationController.java +++ b/packages/SystemUI/src/com/android/systemui/accessibility/FullscreenMagnificationController.java @@ -30,6 +30,8 @@ import android.content.res.Configuration; import android.graphics.PixelFormat; import android.graphics.Rect; import android.graphics.Region; +import android.graphics.drawable.GradientDrawable; +import android.hardware.display.DisplayManager; import android.os.Handler; import android.util.Log; import android.view.AttachedSurfaceControl; @@ -49,6 +51,8 @@ import androidx.annotation.NonNull; import androidx.annotation.UiThread; import com.android.internal.annotations.VisibleForTesting; +import com.android.internal.policy.ScreenDecorationsUtils; +import com.android.systemui.Flags; import com.android.systemui.dagger.qualifiers.Main; import com.android.systemui.res.R; import com.android.systemui.util.leak.RotationUtils; @@ -70,6 +74,7 @@ public class FullscreenMagnificationController implements ComponentCallbacks { private SurfaceControl.Transaction mTransaction; private View mFullscreenBorder = null; private int mBorderOffset; + private int mBorderStoke; private final int mDisplayId; private static final Region sEmptyRegion = new Region(); private ValueAnimator mShowHideBorderAnimator; @@ -86,16 +91,20 @@ public class FullscreenMagnificationController implements ComponentCallbacks { } }; private final long mLongAnimationTimeMs; + private final DisplayManager mDisplayManager; + private final DisplayManager.DisplayListener mDisplayListener; + private String mCurrentDisplayUniqueId; public FullscreenMagnificationController( @UiContext Context context, @Main Handler handler, @Main Executor executor, + DisplayManager displayManager, AccessibilityManager accessibilityManager, WindowManager windowManager, IWindowManager iWindowManager, Supplier<SurfaceControlViewHost> scvhSupplier) { - this(context, handler, executor, accessibilityManager, + this(context, handler, executor, displayManager, accessibilityManager, windowManager, iWindowManager, scvhSupplier, new SurfaceControl.Transaction(), null); } @@ -105,6 +114,7 @@ public class FullscreenMagnificationController implements ComponentCallbacks { @UiContext Context context, @Main Handler handler, @Main Executor executor, + DisplayManager displayManager, AccessibilityManager accessibilityManager, WindowManager windowManager, IWindowManager iWindowManager, @@ -120,10 +130,7 @@ public class FullscreenMagnificationController implements ComponentCallbacks { mWindowBounds = mWindowManager.getCurrentWindowMetrics().getBounds(); mTransaction = transaction; mScvhSupplier = scvhSupplier; - mBorderOffset = mContext.getResources().getDimensionPixelSize( - R.dimen.magnifier_border_width_fullscreen_with_offset) - - mContext.getResources().getDimensionPixelSize( - R.dimen.magnifier_border_width_fullscreen); + updateDimensions(); mDisplayId = mContext.getDisplayId(); mConfiguration = new Configuration(context.getResources().getConfiguration()); mLongAnimationTimeMs = mContext.getResources().getInteger( @@ -140,6 +147,31 @@ public class FullscreenMagnificationController implements ComponentCallbacks { } } }); + mCurrentDisplayUniqueId = mContext.getDisplayNoVerify().getUniqueId(); + mDisplayManager = displayManager; + mDisplayListener = new DisplayManager.DisplayListener() { + @Override + public void onDisplayAdded(int displayId) { + // Do nothing + } + + @Override + public void onDisplayRemoved(int displayId) { + // Do nothing + } + + @Override + public void onDisplayChanged(int displayId) { + final String uniqueId = mContext.getDisplayNoVerify().getUniqueId(); + if (uniqueId.equals(mCurrentDisplayUniqueId)) { + // Same unique ID means the physical display doesn't change. Early return. + return; + } + + mCurrentDisplayUniqueId = uniqueId; + applyCornerRadiusToBorder(); + } + }; } private ValueAnimator createNullTargetObjectAnimator() { @@ -180,10 +212,15 @@ public class FullscreenMagnificationController implements ComponentCallbacks { } mContext.unregisterComponentCallbacks(this); + mShowHideBorderAnimator.reverse(); } private void cleanUpBorder() { + if (Flags.updateCornerRadiusOnDisplayChanged()) { + mDisplayManager.unregisterDisplayListener(mDisplayListener); + } + if (mSurfaceControlViewHost != null) { mSurfaceControlViewHost.release(); mSurfaceControlViewHost = null; @@ -226,6 +263,9 @@ public class FullscreenMagnificationController implements ComponentCallbacks { } catch (Exception e) { Log.w(TAG, "Failed to register rotation watcher", e); } + if (Flags.updateCornerRadiusOnDisplayChanged()) { + mHandler.post(this::applyCornerRadiusToBorder); + } } mTransaction @@ -247,6 +287,9 @@ public class FullscreenMagnificationController implements ComponentCallbacks { mAccessibilityManager.attachAccessibilityOverlayToDisplay( mDisplayId, mBorderSurfaceControl); + if (Flags.updateCornerRadiusOnDisplayChanged()) { + mDisplayManager.registerDisplayListener(mDisplayListener, mHandler); + } applyTouchableRegion(); } @@ -304,6 +347,11 @@ public class FullscreenMagnificationController implements ComponentCallbacks { final int newWidth = mWindowBounds.width() + 2 * mBorderOffset; final int newHeight = mWindowBounds.height() + 2 * mBorderOffset; mSurfaceControlViewHost.relayout(newWidth, newHeight); + if (Flags.updateCornerRadiusOnDisplayChanged()) { + // Recenter the border + mTransaction.setPosition( + mBorderSurfaceControl, -mBorderOffset, -mBorderOffset).apply(); + } } // Rotating from Landscape to ReverseLandscape will not trigger the config changes in @@ -352,6 +400,22 @@ public class FullscreenMagnificationController implements ComponentCallbacks { R.dimen.magnifier_border_width_fullscreen_with_offset) - mContext.getResources().getDimensionPixelSize( R.dimen.magnifier_border_width_fullscreen); + mBorderStoke = mContext.getResources().getDimensionPixelSize( + R.dimen.magnifier_border_width_fullscreen_with_offset); + } + + private void applyCornerRadiusToBorder() { + if (!isActivated()) { + return; + } + + float cornerRadius = ScreenDecorationsUtils.getWindowCornerRadius(mContext); + GradientDrawable backgroundDrawable = (GradientDrawable) mFullscreenBorder.getBackground(); + backgroundDrawable.setStroke( + mBorderStoke, + mContext.getResources().getColor( + R.color.magnification_border_color, mContext.getTheme())); + backgroundDrawable.setCornerRadius(cornerRadius); } @Override diff --git a/packages/SystemUI/src/com/android/systemui/accessibility/MagnificationImpl.java b/packages/SystemUI/src/com/android/systemui/accessibility/MagnificationImpl.java index e9c9bc7799a5..93c4630cd0cd 100644 --- a/packages/SystemUI/src/com/android/systemui/accessibility/MagnificationImpl.java +++ b/packages/SystemUI/src/com/android/systemui/accessibility/MagnificationImpl.java @@ -149,6 +149,7 @@ public class MagnificationImpl implements Magnification, CommandQueue.Callbacks private final Context mContext; private final Handler mHandler; private final Executor mExecutor; + private final DisplayManager mDisplayManager; private final IWindowManager mIWindowManager; FullscreenMagnificationControllerSupplier(Context context, @@ -159,6 +160,7 @@ public class MagnificationImpl implements Magnification, CommandQueue.Callbacks mContext = context; mHandler = handler; mExecutor = executor; + mDisplayManager = displayManager; mIWindowManager = iWindowManager; } @@ -173,6 +175,7 @@ public class MagnificationImpl implements Magnification, CommandQueue.Callbacks windowContext, mHandler, mExecutor, + mDisplayManager, windowContext.getSystemService(AccessibilityManager.class), windowContext.getSystemService(WindowManager.class), mIWindowManager, diff --git a/packages/SystemUI/src/com/android/systemui/accessibility/extradim/ExtraDimDialogDelegate.kt b/packages/SystemUI/src/com/android/systemui/accessibility/extradim/ExtraDimDialogDelegate.kt new file mode 100644 index 000000000000..fcb12068207e --- /dev/null +++ b/packages/SystemUI/src/com/android/systemui/accessibility/extradim/ExtraDimDialogDelegate.kt @@ -0,0 +1,93 @@ +/* + * Copyright (C) 2024 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package com.android.systemui.accessibility.extradim + +import android.content.Context +import android.content.DialogInterface +import android.os.Bundle +import android.view.LayoutInflater +import android.view.accessibility.AccessibilityManager +import android.widget.Toast +import com.android.internal.accessibility.AccessibilityShortcutController +import com.android.internal.accessibility.common.ShortcutConstants +import com.android.systemui.dagger.qualifiers.Application +import com.android.systemui.dagger.qualifiers.Background +import com.android.systemui.res.R +import com.android.systemui.settings.UserTracker +import com.android.systemui.statusbar.phone.SystemUIDialog +import javax.inject.Inject +import kotlinx.coroutines.CoroutineDispatcher +import kotlinx.coroutines.CoroutineScope +import kotlinx.coroutines.launch +import kotlinx.coroutines.withContext + +/** Dialog for removing Extra Dim shortcuts. */ +class ExtraDimDialogDelegate +@Inject +constructor( + private val context: Context, + @Application private val applicationScope: CoroutineScope, + @Background private val backgroundDispatcher: CoroutineDispatcher, + private val systemUIDialogFactory: SystemUIDialog.Factory, + private val accessibilityManager: AccessibilityManager, + private val userTracker: UserTracker, +) : SystemUIDialog.Delegate { + + private val onClickListener: DialogInterface.OnClickListener = + DialogInterface.OnClickListener { dialog, _ -> + applicationScope.launch { + dialog.dismiss() + onRemoveExtraDimShortcutButtonClicked() + Toast.makeText( + context, + context.getText(R.string.accessibility_deprecate_extra_dim_dialog_toast), + Toast.LENGTH_LONG + ) + .show() + } + } + + override fun beforeCreate(dialog: SystemUIDialog, savedInstanceState: Bundle?) { + dialog.setTitle(R.string.accessibility_deprecate_extra_dim_dialog_title) + dialog.setView( + LayoutInflater.from(dialog.context) + .inflate(R.layout.accessibility_deprecate_extra_dim_dialog, null) + ) + dialog.setPositiveButton( + R.string.accessibility_deprecate_extra_dim_dialog_button, + onClickListener + ) + } + + override fun createDialog(): SystemUIDialog { + val dialog = systemUIDialogFactory.create(this) + dialog.setCanceledOnTouchOutside(false) + return dialog + } + + private suspend fun onRemoveExtraDimShortcutButtonClicked() = + withContext(backgroundDispatcher) { + accessibilityManager.enableShortcutsForTargets( + /* enable= */ false, + ShortcutConstants.UserShortcutType.ALL, + setOf( + AccessibilityShortcutController.REDUCE_BRIGHT_COLORS_COMPONENT_NAME + .flattenToString() + ), + userTracker.userId + ) + } +} diff --git a/packages/SystemUI/src/com/android/systemui/accessibility/extradim/ExtraDimDialogManager.kt b/packages/SystemUI/src/com/android/systemui/accessibility/extradim/ExtraDimDialogManager.kt new file mode 100644 index 000000000000..e1297d32504b --- /dev/null +++ b/packages/SystemUI/src/com/android/systemui/accessibility/extradim/ExtraDimDialogManager.kt @@ -0,0 +1,52 @@ +/* + * Copyright (C) 2024 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package com.android.systemui.accessibility.extradim + +import androidx.annotation.VisibleForTesting +import com.android.systemui.dagger.SysUISingleton +import com.android.systemui.plugins.ActivityStarter +import com.android.systemui.statusbar.phone.SystemUIDialog +import javax.inject.Inject +import javax.inject.Provider + +/** Managing the Extra Dim Dialog behaviors. */ +@SysUISingleton +class ExtraDimDialogManager +@Inject +constructor( + private val extraDimDialogDelegateProvider: Provider<ExtraDimDialogDelegate>, + private val mActivityStarter: ActivityStarter +) { + private var dialog: SystemUIDialog? = null + + @VisibleForTesting(otherwise = VisibleForTesting.PROTECTED) + fun dismissKeyguardIfNeededAndShowDialog() { + mActivityStarter.executeRunnableDismissingKeyguard( + { showRemoveExtraDimShortcutsDialog() }, + /* cancelAction= */ null, + /* dismissShade= */ false, + /* afterKeyguardGone= */ true, + /* deferred= */ false + ) + } + + /** Show the dialog for removing all Extra Dim shortcuts. */ + private fun showRemoveExtraDimShortcutsDialog() { + dialog?.dismiss() + dialog = extraDimDialogDelegateProvider.get().createDialog() + dialog!!.show() + } +} diff --git a/packages/SystemUI/src/com/android/systemui/accessibility/extradim/ExtraDimDialogReceiver.kt b/packages/SystemUI/src/com/android/systemui/accessibility/extradim/ExtraDimDialogReceiver.kt new file mode 100644 index 000000000000..405993a4479f --- /dev/null +++ b/packages/SystemUI/src/com/android/systemui/accessibility/extradim/ExtraDimDialogReceiver.kt @@ -0,0 +1,53 @@ +/* + * Copyright (C) 2024 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package com.android.systemui.accessibility.extradim + +import android.content.BroadcastReceiver +import android.content.Context +import android.content.Intent +import com.android.server.display.feature.flags.Flags +import javax.inject.Inject + +/** + * BroadcastReceiver for handling [ExtraDimDialogDelegate] intent. + * + * This is not exported. Need to call from framework and use SYSTEM user to send the intent. + */ +class ExtraDimDialogReceiver +@Inject +constructor( + private val extraDimDialogManager: ExtraDimDialogManager, +) : BroadcastReceiver() { + + override fun onReceive(context: Context, intent: Intent) { + if ( + !Flags.evenDimmer() || + !context + .getResources() + .getBoolean(com.android.internal.R.bool.config_evenDimmerEnabled) + ) { + return + } + + if (ACTION == intent.action) { + extraDimDialogManager.dismissKeyguardIfNeededAndShowDialog() + } + } + + companion object { + const val ACTION = "com.android.systemui.action.LAUNCH_REMOVE_EXTRA_DIM_DIALOG" + } +} diff --git a/packages/SystemUI/src/com/android/systemui/accessibility/hearingaid/HearingDevicesDialogDelegate.java b/packages/SystemUI/src/com/android/systemui/accessibility/hearingaid/HearingDevicesDialogDelegate.java index f041f4d5963f..083f1db07886 100644 --- a/packages/SystemUI/src/com/android/systemui/accessibility/hearingaid/HearingDevicesDialogDelegate.java +++ b/packages/SystemUI/src/com/android/systemui/accessibility/hearingaid/HearingDevicesDialogDelegate.java @@ -52,6 +52,7 @@ import androidx.annotation.VisibleForTesting; import androidx.recyclerview.widget.LinearLayoutManager; import androidx.recyclerview.widget.RecyclerView; +import com.android.internal.logging.UiEventLogger; import com.android.settingslib.bluetooth.BluetoothCallback; import com.android.settingslib.bluetooth.CachedBluetoothDevice; import com.android.settingslib.bluetooth.HapClientProfile; @@ -104,6 +105,7 @@ public class HearingDevicesDialogDelegate implements SystemUIDialog.Delegate, private final AudioManager mAudioManager; private final LocalBluetoothProfileManager mProfileManager; private final HapClientProfile mHapClientProfile; + private final UiEventLogger mUiEventLogger; private HearingDevicesListAdapter mDeviceListAdapter; private HearingDevicesPresetsController mPresetsController; private Context mApplicationContext; @@ -163,7 +165,8 @@ public class HearingDevicesDialogDelegate implements SystemUIDialog.Delegate, DialogTransitionAnimator dialogTransitionAnimator, @Nullable LocalBluetoothManager localBluetoothManager, @Main Handler handler, - AudioManager audioManager) { + AudioManager audioManager, + UiEventLogger uiEventLogger) { mApplicationContext = applicationContext; mShowPairNewDevice = showPairNewDevice; mSystemUIDialogFactory = systemUIDialogFactory; @@ -174,6 +177,7 @@ public class HearingDevicesDialogDelegate implements SystemUIDialog.Delegate, mAudioManager = audioManager; mProfileManager = localBluetoothManager.getProfileManager(); mHapClientProfile = mProfileManager.getHapClientProfile(); + mUiEventLogger = uiEventLogger; } @Override @@ -187,6 +191,7 @@ public class HearingDevicesDialogDelegate implements SystemUIDialog.Delegate, @Override public void onDeviceItemGearClicked(@NonNull DeviceItem deviceItem, @NonNull View view) { + mUiEventLogger.log(HearingDevicesUiEvent.HEARING_DEVICES_GEAR_CLICK); dismissDialogIfExists(); Intent intent = new Intent(ACTION_BLUETOOTH_DEVICE_DETAILS); Bundle bundle = new Bundle(); @@ -198,13 +203,21 @@ public class HearingDevicesDialogDelegate implements SystemUIDialog.Delegate, } @Override - public void onDeviceItemOnClicked(@NonNull DeviceItem deviceItem, @NonNull View view) { + public void onDeviceItemClicked(@NonNull DeviceItem deviceItem, @NonNull View view) { CachedBluetoothDevice cachedBluetoothDevice = deviceItem.getCachedBluetoothDevice(); switch (deviceItem.getType()) { - case ACTIVE_MEDIA_BLUETOOTH_DEVICE, CONNECTED_BLUETOOTH_DEVICE -> - cachedBluetoothDevice.disconnect(); - case AVAILABLE_MEDIA_BLUETOOTH_DEVICE -> cachedBluetoothDevice.setActive(); - case SAVED_BLUETOOTH_DEVICE -> cachedBluetoothDevice.connect(); + case ACTIVE_MEDIA_BLUETOOTH_DEVICE, CONNECTED_BLUETOOTH_DEVICE -> { + mUiEventLogger.log(HearingDevicesUiEvent.HEARING_DEVICES_DISCONNECT); + cachedBluetoothDevice.disconnect(); + } + case AVAILABLE_MEDIA_BLUETOOTH_DEVICE -> { + mUiEventLogger.log(HearingDevicesUiEvent.HEARING_DEVICES_SET_ACTIVE); + cachedBluetoothDevice.setActive(); + } + case SAVED_BLUETOOTH_DEVICE -> { + mUiEventLogger.log(HearingDevicesUiEvent.HEARING_DEVICES_CONNECT); + cachedBluetoothDevice.connect(); + } } } @@ -262,6 +275,7 @@ public class HearingDevicesDialogDelegate implements SystemUIDialog.Delegate, if (mLocalBluetoothManager == null) { return; } + mUiEventLogger.log(HearingDevicesUiEvent.HEARING_DEVICES_DIALOG_SHOW); mPairButton = dialog.requireViewById(R.id.pair_new_device_button); mDeviceList = dialog.requireViewById(R.id.device_list); mPresetSpinner = dialog.requireViewById(R.id.preset_spinner); @@ -341,12 +355,17 @@ public class HearingDevicesDialogDelegate implements SystemUIDialog.Delegate, } }); + // Refresh the spinner and setSelection(index, false) before setOnItemSelectedListener() to + // avoid extra onItemSelected() get called when first register the listener. + final List<BluetoothHapPresetInfo> presetInfos = mPresetsController.getAllPresetInfo(); + final int activePresetIndex = mPresetsController.getActivePresetIndex(); + refreshPresetInfoAdapter(presetInfos, activePresetIndex); mPresetSpinner.setOnItemSelectedListener(new AdapterView.OnItemSelectedListener() { @Override public void onItemSelected(AdapterView<?> parent, View view, int position, long id) { + mUiEventLogger.log(HearingDevicesUiEvent.HEARING_DEVICES_PRESET_SELECT); mPresetsController.selectPreset( mPresetsController.getAllPresetInfo().get(position).getIndex()); - mPresetSpinner.setSelection(position); } @Override @@ -354,9 +373,6 @@ public class HearingDevicesDialogDelegate implements SystemUIDialog.Delegate, // Do nothing } }); - final List<BluetoothHapPresetInfo> presetInfos = mPresetsController.getAllPresetInfo(); - final int activePresetIndex = mPresetsController.getActivePresetIndex(); - refreshPresetInfoAdapter(presetInfos, activePresetIndex); mPresetSpinner.setVisibility( (activeHearingDevice != null && activeHearingDevice.isConnectedHapClientDevice() && !mPresetInfoAdapter.isEmpty()) ? VISIBLE : GONE); @@ -365,6 +381,7 @@ public class HearingDevicesDialogDelegate implements SystemUIDialog.Delegate, private void setupPairNewDeviceButton(SystemUIDialog dialog, @Visibility int visibility) { if (visibility == VISIBLE) { mPairButton.setOnClickListener(v -> { + mUiEventLogger.log(HearingDevicesUiEvent.HEARING_DEVICES_PAIR); dismissDialogIfExists(); final Intent intent = new Intent(Settings.ACTION_HEARING_DEVICE_PAIRING_SETTINGS); intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK | Intent.FLAG_ACTIVITY_CLEAR_TASK); @@ -413,7 +430,7 @@ public class HearingDevicesDialogDelegate implements SystemUIDialog.Delegate, final int size = mPresetInfoAdapter.getCount(); for (int position = 0; position < size; position++) { if (presetInfos.get(position).getIndex() == activePresetIndex) { - mPresetSpinner.setSelection(position); + mPresetSpinner.setSelection(position, /* animate= */ false); } } } @@ -464,12 +481,15 @@ public class HearingDevicesDialogDelegate implements SystemUIDialog.Delegate, text.setText(item.getToolName()); Intent intent = item.getToolIntent(); intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK | Intent.FLAG_ACTIVITY_CLEAR_TASK); - view.setOnClickListener( - v -> { - dismissDialogIfExists(); - mActivityStarter.postStartActivityDismissingKeyguard(intent, /* delay= */ 0, - mDialogTransitionAnimator.createActivityTransitionController(view)); - }); + view.setOnClickListener(v -> { + final String name = intent.getComponent() != null + ? intent.getComponent().flattenToString() + : intent.getPackage() + "/" + intent.getAction(); + mUiEventLogger.log(HearingDevicesUiEvent.HEARING_DEVICES_RELATED_TOOL_CLICK, 0, name); + dismissDialogIfExists(); + mActivityStarter.postStartActivityDismissingKeyguard(intent, /* delay= */ 0, + mDialogTransitionAnimator.createActivityTransitionController(view)); + }); return view; } diff --git a/packages/SystemUI/src/com/android/systemui/accessibility/hearingaid/HearingDevicesListAdapter.java b/packages/SystemUI/src/com/android/systemui/accessibility/hearingaid/HearingDevicesListAdapter.java index 737805b4d62f..b46b8fe4f6c8 100644 --- a/packages/SystemUI/src/com/android/systemui/accessibility/hearingaid/HearingDevicesListAdapter.java +++ b/packages/SystemUI/src/com/android/systemui/accessibility/hearingaid/HearingDevicesListAdapter.java @@ -96,7 +96,7 @@ public class HearingDevicesListAdapter extends RecyclerView.Adapter<RecyclerView * @param deviceItem bluetooth device item * @param view the view that was clicked */ - void onDeviceItemOnClicked(@NonNull DeviceItem deviceItem, @NonNull View view); + void onDeviceItemClicked(@NonNull DeviceItem deviceItem, @NonNull View view); } private static class DeviceItemViewHolder extends RecyclerView.ViewHolder { @@ -119,7 +119,7 @@ public class HearingDevicesListAdapter extends RecyclerView.Adapter<RecyclerView public void bindView(DeviceItem item, HearingDeviceItemCallback callback) { mContainer.setEnabled(item.isEnabled()); - mContainer.setOnClickListener(view -> callback.onDeviceItemOnClicked(item, view)); + mContainer.setOnClickListener(view -> callback.onDeviceItemClicked(item, view)); Integer backgroundResId = item.getBackground(); if (backgroundResId != null) { mContainer.setBackground(mContext.getDrawable(item.getBackground())); diff --git a/packages/SystemUI/src/com/android/systemui/accessibility/hearingaid/HearingDevicesUiEvent.java b/packages/SystemUI/src/com/android/systemui/accessibility/hearingaid/HearingDevicesUiEvent.java new file mode 100644 index 000000000000..3fbe56eccef2 --- /dev/null +++ b/packages/SystemUI/src/com/android/systemui/accessibility/hearingaid/HearingDevicesUiEvent.java @@ -0,0 +1,51 @@ +/* + * Copyright (C) 2024 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.android.systemui.accessibility.hearingaid; + +import com.android.internal.logging.UiEvent; +import com.android.internal.logging.UiEventLogger; + +public enum HearingDevicesUiEvent implements UiEventLogger.UiEventEnum { + + @UiEvent(doc = "Hearing devices dialog is shown") + HEARING_DEVICES_DIALOG_SHOW(1848), + @UiEvent(doc = "Pair new device") + HEARING_DEVICES_PAIR(1849), + @UiEvent(doc = "Connect to the device") + HEARING_DEVICES_CONNECT(1850), + @UiEvent(doc = "Disconnect from the device") + HEARING_DEVICES_DISCONNECT(1851), + @UiEvent(doc = "Set the device as active device") + HEARING_DEVICES_SET_ACTIVE(1852), + @UiEvent(doc = "Click on the device gear to enter device detail page") + HEARING_DEVICES_GEAR_CLICK(1853), + @UiEvent(doc = "Select a preset from preset spinner") + HEARING_DEVICES_PRESET_SELECT(1854), + @UiEvent(doc = "Click on related tool") + HEARING_DEVICES_RELATED_TOOL_CLICK(1856); + + private final int mId; + + HearingDevicesUiEvent(int id) { + mId = id; + } + + @Override + public int getId() { + return mId; + } +} diff --git a/packages/SystemUI/src/com/android/systemui/biometrics/UdfpsController.java b/packages/SystemUI/src/com/android/systemui/biometrics/UdfpsController.java index 3dd375846499..5ffb9ab26bb0 100644 --- a/packages/SystemUI/src/com/android/systemui/biometrics/UdfpsController.java +++ b/packages/SystemUI/src/com/android/systemui/biometrics/UdfpsController.java @@ -56,13 +56,13 @@ import android.view.HapticFeedbackConstants; import android.view.LayoutInflater; import android.view.MotionEvent; import android.view.View; -import android.view.WindowManager; import android.view.accessibility.AccessibilityManager; import androidx.annotation.NonNull; import androidx.annotation.Nullable; import androidx.annotation.OptIn; +import com.android.app.viewcapture.ViewCaptureAwareWindowManager; import com.android.internal.R; import com.android.internal.annotations.VisibleForTesting; import com.android.internal.logging.InstanceId; @@ -147,7 +147,7 @@ public class UdfpsController implements DozeReceiver, Dumpable { private final Execution mExecution; private final FingerprintManager mFingerprintManager; @NonNull private final LayoutInflater mInflater; - private final WindowManager mWindowManager; + private final ViewCaptureAwareWindowManager mWindowManager; private final DelayableExecutor mFgExecutor; @NonNull private final Executor mBiometricExecutor; @NonNull private final StatusBarStateController mStatusBarStateController; @@ -693,7 +693,7 @@ public class UdfpsController implements DozeReceiver, Dumpable { @NonNull Execution execution, @NonNull LayoutInflater inflater, @Nullable FingerprintManager fingerprintManager, - @NonNull WindowManager windowManager, + @NonNull ViewCaptureAwareWindowManager viewCaptureAwareWindowManager, @NonNull StatusBarStateController statusBarStateController, @Main DelayableExecutor fgExecutor, @NonNull StatusBarKeyguardViewManager statusBarKeyguardViewManager, @@ -741,7 +741,7 @@ public class UdfpsController implements DozeReceiver, Dumpable { // The fingerprint manager is queried for UDFPS before this class is constructed, so the // fingerprint manager should never be null. mFingerprintManager = checkNotNull(fingerprintManager); - mWindowManager = windowManager; + mWindowManager = viewCaptureAwareWindowManager; mFgExecutor = fgExecutor; mStatusBarStateController = statusBarStateController; mKeyguardStateController = keyguardStateController; diff --git a/packages/SystemUI/src/com/android/systemui/biometrics/UdfpsControllerOverlay.kt b/packages/SystemUI/src/com/android/systemui/biometrics/UdfpsControllerOverlay.kt index e03d160adc8d..1bac0bc26a94 100644 --- a/packages/SystemUI/src/com/android/systemui/biometrics/UdfpsControllerOverlay.kt +++ b/packages/SystemUI/src/com/android/systemui/biometrics/UdfpsControllerOverlay.kt @@ -44,6 +44,7 @@ import android.view.accessibility.AccessibilityManager import android.view.accessibility.AccessibilityManager.TouchExplorationStateChangeListener import androidx.annotation.LayoutRes import androidx.annotation.VisibleForTesting +import com.android.app.viewcapture.ViewCaptureAwareWindowManager import com.android.keyguard.KeyguardUpdateMonitor import com.android.systemui.animation.ActivityTransitionAnimator import com.android.systemui.biometrics.domain.interactor.UdfpsOverlayInteractor @@ -94,7 +95,7 @@ class UdfpsControllerOverlay constructor( private val context: Context, private val inflater: LayoutInflater, - private val windowManager: WindowManager, + private val windowManager: ViewCaptureAwareWindowManager, private val accessibilityManager: AccessibilityManager, private val statusBarStateController: StatusBarStateController, private val statusBarKeyguardViewManager: StatusBarKeyguardViewManager, diff --git a/packages/SystemUI/src/com/android/systemui/biometrics/ui/binder/BiometricViewBinder.kt b/packages/SystemUI/src/com/android/systemui/biometrics/ui/binder/BiometricViewBinder.kt index ecfbd66c5e64..9f6d565875e2 100644 --- a/packages/SystemUI/src/com/android/systemui/biometrics/ui/binder/BiometricViewBinder.kt +++ b/packages/SystemUI/src/com/android/systemui/biometrics/ui/binder/BiometricViewBinder.kt @@ -382,8 +382,12 @@ object BiometricViewBinder { backgroundView.importantForAccessibility = IMPORTANT_FOR_ACCESSIBILITY_NO - // Allow icon to be used as confirmation button with a11y enabled - if (accessibilityManager.isTouchExplorationEnabled) { + // Allow icon to be used as confirmation button with udfps and a11y + // enabled + if ( + accessibilityManager.isTouchExplorationEnabled && + modalities.hasUdfps + ) { iconOverlayView.setOnClickListener { viewModel.confirmAuthenticated() } diff --git a/packages/SystemUI/src/com/android/systemui/biometrics/ui/viewmodel/PromptIconViewModel.kt b/packages/SystemUI/src/com/android/systemui/biometrics/ui/viewmodel/PromptIconViewModel.kt index 6c83dac148b2..c08914380117 100644 --- a/packages/SystemUI/src/com/android/systemui/biometrics/ui/viewmodel/PromptIconViewModel.kt +++ b/packages/SystemUI/src/com/android/systemui/biometrics/ui/viewmodel/PromptIconViewModel.kt @@ -469,7 +469,7 @@ constructor( if (isPendingConfirmation) { when (sensorType) { FingerprintSensorType.POWER_BUTTON -> -1 - else -> R.string.fingerprint_dialog_authenticated_confirmation + else -> R.string.biometric_dialog_confirm } } else if (isAuthenticating || isAuthenticated) { when (sensorType) { diff --git a/packages/SystemUI/src/com/android/systemui/camera/CameraGestureHelper.kt b/packages/SystemUI/src/com/android/systemui/camera/CameraGestureHelper.kt index ecbd3f97f4e5..6757edba8ac3 100644 --- a/packages/SystemUI/src/com/android/systemui/camera/CameraGestureHelper.kt +++ b/packages/SystemUI/src/com/android/systemui/camera/CameraGestureHelper.kt @@ -19,6 +19,7 @@ package com.android.systemui.camera import android.app.ActivityManager import android.app.ActivityOptions import android.app.IActivityTaskManager +import android.app.admin.DevicePolicyManager import android.content.ContentResolver import android.content.Context import android.content.Intent @@ -32,8 +33,8 @@ import com.android.systemui.dagger.SysUISingleton import com.android.systemui.dagger.qualifiers.Main import com.android.systemui.plugins.ActivityStarter import com.android.systemui.shared.system.ActivityManagerKt.isInForeground +import com.android.systemui.statusbar.NotificationLockscreenUserManager import com.android.systemui.statusbar.StatusBarState -import com.android.systemui.statusbar.phone.CentralSurfaces import com.android.systemui.statusbar.phone.StatusBarKeyguardViewManager import com.android.systemui.statusbar.policy.KeyguardStateController import com.android.systemui.user.domain.interactor.SelectedUserInteractor @@ -45,9 +46,10 @@ import javax.inject.Inject * the camera). */ @SysUISingleton -class CameraGestureHelper @Inject constructor( +class CameraGestureHelper +@Inject +constructor( private val context: Context, - private val centralSurfaces: CentralSurfaces, private val keyguardStateController: KeyguardStateController, private val statusBarKeyguardViewManager: StatusBarKeyguardViewManager, private val packageManager: PackageManager, @@ -59,24 +61,25 @@ class CameraGestureHelper @Inject constructor( private val contentResolver: ContentResolver, @Main private val uiExecutor: Executor, private val selectedUserInteractor: SelectedUserInteractor, + private val devicePolicyManager: DevicePolicyManager, + private val lockscreenUserManager: NotificationLockscreenUserManager, ) { - /** - * Whether the camera application can be launched for the camera launch gesture. - */ + /** Whether the camera application can be launched for the camera launch gesture. */ fun canCameraGestureBeLaunched(statusBarState: Int): Boolean { - if (!centralSurfaces.isCameraAllowedByAdmin) { + if (!isCameraAllowedByAdmin()) { return false } - val resolveInfo: ResolveInfo? = packageManager.resolveActivityAsUser( - getStartCameraIntent(selectedUserInteractor.getSelectedUserId()), - PackageManager.MATCH_DEFAULT_ONLY, - selectedUserInteractor.getSelectedUserId() - ) + val resolveInfo: ResolveInfo? = + packageManager.resolveActivityAsUser( + getStartCameraIntent(selectedUserInteractor.getSelectedUserId()), + PackageManager.MATCH_DEFAULT_ONLY, + selectedUserInteractor.getSelectedUserId() + ) val resolvedPackage = resolveInfo?.activityInfo?.packageName return (resolvedPackage != null && - (statusBarState != StatusBarState.SHADE || - !activityManager.isInForeground(resolvedPackage))) + (statusBarState != StatusBarState.SHADE || + !activityManager.isInForeground(resolvedPackage))) } /** @@ -87,9 +90,11 @@ class CameraGestureHelper @Inject constructor( fun launchCamera(source: Int) { val intent: Intent = getStartCameraIntent(selectedUserInteractor.getSelectedUserId()) intent.putExtra(CameraIntents.EXTRA_LAUNCH_SOURCE, source) - val wouldLaunchResolverActivity = activityIntentHelper.wouldLaunchResolverActivity( - intent, selectedUserInteractor.getSelectedUserId() - ) + val wouldLaunchResolverActivity = + activityIntentHelper.wouldLaunchResolverActivity( + intent, + selectedUserInteractor.getSelectedUserId() + ) if (CameraIntents.isSecureCameraIntent(intent) && !wouldLaunchResolverActivity) { uiExecutor.execute { // Normally an activity will set its requested rotation animation on its window. @@ -101,7 +106,7 @@ class CameraGestureHelper @Inject constructor( val activityOptions = ActivityOptions.makeBasic() activityOptions.setDisallowEnterPictureInPictureWhileLaunching(true) activityOptions.rotationAnimationHint = - WindowManager.LayoutParams.ROTATION_ANIMATION_SEAMLESS + WindowManager.LayoutParams.ROTATION_ANIMATION_SEAMLESS try { activityTaskManager.startActivityAsUser( null, @@ -118,11 +123,7 @@ class CameraGestureHelper @Inject constructor( selectedUserInteractor.getSelectedUserId(true), ) } catch (e: RemoteException) { - Log.w( - "CameraGestureHelper", - "Unable to start camera activity", - e - ) + Log.w("CameraGestureHelper", "Unable to start camera activity", e) } } } else { @@ -131,9 +132,6 @@ class CameraGestureHelper @Inject constructor( activityStarter.startActivity(intent, false /* dismissShade */) } - // Call this to make sure that the keyguard returns if the app that is being launched - // crashes after a timeout. - centralSurfaces.startLaunchTransitionTimeout() // Call this to make sure the keyguard is ready to be dismissed once the next intent is // handled by the OS (in our case it is the activity we started right above) statusBarKeyguardViewManager.readyForKeyguardDone() @@ -152,4 +150,17 @@ class CameraGestureHelper @Inject constructor( cameraIntents.getInsecureCameraIntent(userId) } } + + private fun isCameraAllowedByAdmin(): Boolean { + if (devicePolicyManager.getCameraDisabled(null, lockscreenUserManager.getCurrentUserId())) { + return false + } else if (keyguardStateController.isShowing() && statusBarKeyguardViewManager.isSecure()) { + // Check if the admin has disabled the camera specifically for the keyguard + return (devicePolicyManager.getKeyguardDisabledFeatures( + null, + lockscreenUserManager.getCurrentUserId() + ) and DevicePolicyManager.KEYGUARD_DISABLE_SECURE_CAMERA) == 0 + } + return true + } } diff --git a/packages/SystemUI/src/com/android/systemui/clipboardoverlay/ClipboardOverlayWindow.java b/packages/SystemUI/src/com/android/systemui/clipboardoverlay/ClipboardOverlayWindow.java index 9dac9b393d60..0dc6fda90b20 100644 --- a/packages/SystemUI/src/com/android/systemui/clipboardoverlay/ClipboardOverlayWindow.java +++ b/packages/SystemUI/src/com/android/systemui/clipboardoverlay/ClipboardOverlayWindow.java @@ -18,10 +18,8 @@ package com.android.systemui.clipboardoverlay; import android.annotation.MainThread; import android.annotation.NonNull; -import android.app.ICompatCameraControlCallback; import android.content.Context; import android.content.res.Configuration; -import android.util.Log; import android.view.View; import android.view.ViewRootImpl; import android.view.ViewTreeObserver; @@ -104,12 +102,6 @@ public class ClipboardOverlayWindow extends PhoneWindow } } - @Override // ViewRootImpl.ActivityConfigCallback - public void requestCompatCameraControl(boolean showControl, boolean transformationApplied, - ICompatCameraControlCallback callback) { - Log.w(TAG, "unexpected requestCompatCameraControl call"); - } - void remove() { final View decorView = peekDecorView(); if (decorView != null && decorView.isAttachedToWindow()) { diff --git a/packages/SystemUI/src/com/android/systemui/communal/data/repository/CommunalSmartspaceRepository.kt b/packages/SystemUI/src/com/android/systemui/communal/data/repository/CommunalSmartspaceRepository.kt index e1d9bef67490..86241a5261d7 100644 --- a/packages/SystemUI/src/com/android/systemui/communal/data/repository/CommunalSmartspaceRepository.kt +++ b/packages/SystemUI/src/com/android/systemui/communal/data/repository/CommunalSmartspaceRepository.kt @@ -19,6 +19,7 @@ package com.android.systemui.communal.data.repository import android.app.smartspace.SmartspaceTarget import android.os.Parcelable import androidx.annotation.VisibleForTesting +import com.android.systemui.Flags.communalTimerFlickerFix import com.android.systemui.communal.data.model.CommunalSmartspaceTimer import com.android.systemui.communal.smartspace.CommunalSmartspaceController import com.android.systemui.dagger.SysUISingleton @@ -80,7 +81,8 @@ constructor( // The view layer should have the instance based smartspaceTargetId instead of // stable id, so that when a new instance of the timer is created, for example, // when it is paused, the view should re-render its remote views. - smartspaceTargetId = target.smartspaceTargetId, + smartspaceTargetId = + if (communalTimerFlickerFix()) stableId else target.smartspaceTargetId, createdTimestampMillis = targetCreationTimes[stableId]!!, remoteViews = target.remoteViews!!, ) diff --git a/packages/SystemUI/src/com/android/systemui/communal/ui/viewmodel/BaseCommunalViewModel.kt b/packages/SystemUI/src/com/android/systemui/communal/ui/viewmodel/BaseCommunalViewModel.kt index 4be93ccde1d5..d1a5a4b8641f 100644 --- a/packages/SystemUI/src/com/android/systemui/communal/ui/viewmodel/BaseCommunalViewModel.kt +++ b/packages/SystemUI/src/com/android/systemui/communal/ui/viewmodel/BaseCommunalViewModel.kt @@ -16,6 +16,7 @@ package com.android.systemui.communal.ui.viewmodel +import android.appwidget.AppWidgetProviderInfo import android.content.ComponentName import android.os.UserHandle import android.view.View @@ -197,6 +198,9 @@ abstract class BaseCommunalViewModel( /** Called as the user request to show the customize widget button. */ open fun onLongClick() {} + /** Called as the UI determines that a new widget has been added to the grid. */ + open fun onNewWidgetAdded(provider: AppWidgetProviderInfo) {} + /** Called when the grid scroll position has been updated. */ open fun onScrollPositionUpdated(firstVisibleItemIndex: Int, firstVisibleItemScroll: Int) { currentScrollIndex = firstVisibleItemIndex diff --git a/packages/SystemUI/src/com/android/systemui/communal/ui/viewmodel/CommunalEditModeViewModel.kt b/packages/SystemUI/src/com/android/systemui/communal/ui/viewmodel/CommunalEditModeViewModel.kt index 5b825d80d9b1..1a86c717b962 100644 --- a/packages/SystemUI/src/com/android/systemui/communal/ui/viewmodel/CommunalEditModeViewModel.kt +++ b/packages/SystemUI/src/com/android/systemui/communal/ui/viewmodel/CommunalEditModeViewModel.kt @@ -19,16 +19,18 @@ package com.android.systemui.communal.ui.viewmodel import android.appwidget.AppWidgetManager import android.appwidget.AppWidgetProviderInfo import android.content.ComponentName +import android.content.Context import android.content.Intent import android.content.pm.PackageManager import android.content.res.Resources import android.os.UserHandle import android.util.Log +import android.view.accessibility.AccessibilityEvent +import android.view.accessibility.AccessibilityManager import androidx.activity.result.ActivityResultLauncher import com.android.internal.logging.UiEventLogger import com.android.systemui.communal.data.model.CommunalWidgetCategories import com.android.systemui.communal.domain.interactor.CommunalInteractor -import com.android.systemui.communal.domain.interactor.CommunalPrefsInteractor import com.android.systemui.communal.domain.interactor.CommunalSceneInteractor import com.android.systemui.communal.domain.interactor.CommunalSettingsInteractor import com.android.systemui.communal.domain.model.CommunalContentModel @@ -37,6 +39,7 @@ import com.android.systemui.communal.shared.log.CommunalUiEvent import com.android.systemui.communal.shared.model.EditModeState import com.android.systemui.communal.widgets.WidgetConfigurator import com.android.systemui.dagger.SysUISingleton +import com.android.systemui.dagger.qualifiers.Application import com.android.systemui.dagger.qualifiers.Background import com.android.systemui.keyguard.domain.interactor.KeyguardTransitionInteractor import com.android.systemui.keyguard.shared.model.KeyguardState @@ -74,8 +77,10 @@ constructor( private val uiEventLogger: UiEventLogger, @CommunalLog logBuffer: LogBuffer, @Background private val backgroundDispatcher: CoroutineDispatcher, - private val communalPrefsInteractor: CommunalPrefsInteractor, private val metricsLogger: CommunalMetricsLogger, + @Application private val context: Context, + private val accessibilityManager: AccessibilityManager, + private val packageManager: PackageManager, ) : BaseCommunalViewModel(communalSceneInteractor, communalInteractor, mediaHost) { private val logger = Logger(logBuffer, "CommunalEditModeViewModel") @@ -156,6 +161,25 @@ constructor( uiEventLogger.log(CommunalUiEvent.COMMUNAL_HUB_REORDER_WIDGET_CANCEL) } + override fun onNewWidgetAdded(provider: AppWidgetProviderInfo) { + if (!accessibilityManager.isEnabled) { + return + } + + // Send an accessibility announcement for the newly added widget + val widgetLabel = provider.loadLabel(packageManager) + val announcementText = + context.getString( + R.string.accessibility_announcement_communal_widget_added, + widgetLabel + ) + accessibilityManager.sendAccessibilityEvent( + AccessibilityEvent(AccessibilityEvent.TYPE_ANNOUNCEMENT).apply { + contentDescription = announcementText + } + ) + } + val isIdleOnCommunal: StateFlow<Boolean> = communalInteractor.isIdleOnCommunal /** Launch the widget picker activity using the given {@link ActivityResultLauncher}. */ diff --git a/packages/SystemUI/src/com/android/systemui/dagger/DefaultBroadcastReceiverBinder.java b/packages/SystemUI/src/com/android/systemui/dagger/DefaultBroadcastReceiverBinder.java index 7ced9322ed38..5a0eb7260ab1 100644 --- a/packages/SystemUI/src/com/android/systemui/dagger/DefaultBroadcastReceiverBinder.java +++ b/packages/SystemUI/src/com/android/systemui/dagger/DefaultBroadcastReceiverBinder.java @@ -19,6 +19,7 @@ package com.android.systemui.dagger; import android.content.BroadcastReceiver; import com.android.systemui.GuestResetOrExitSessionReceiver; +import com.android.systemui.accessibility.extradim.ExtraDimDialogReceiver; import com.android.systemui.accessibility.hearingaid.HearingDevicesDialogReceiver; import com.android.systemui.media.dialog.MediaOutputDialogReceiver; import com.android.systemui.people.widget.PeopleSpaceWidgetPinnedReceiver; @@ -88,4 +89,13 @@ public abstract class DefaultBroadcastReceiverBinder { @ClassKey(HearingDevicesDialogReceiver.class) public abstract BroadcastReceiver bindHearingDevicesDialogReceiver( HearingDevicesDialogReceiver broadcastReceiver); + + /** + * + */ + @Binds + @IntoMap + @ClassKey(ExtraDimDialogReceiver.class) + public abstract BroadcastReceiver bindExtraDimDialogReceiver( + ExtraDimDialogReceiver broadcastReceiver); } diff --git a/packages/SystemUI/src/com/android/systemui/dagger/SystemUICoreStartableModule.kt b/packages/SystemUI/src/com/android/systemui/dagger/SystemUICoreStartableModule.kt index 88601dab891d..42866465a0cc 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.dreams.AssistantAttentionMonitor import com.android.systemui.dreams.DreamMonitor import com.android.systemui.dreams.homecontrols.HomeControlsDreamStartable import com.android.systemui.globalactions.GlobalActionsComponent +import com.android.systemui.inputdevice.oobe.KeyboardTouchpadOobeTutorialCoreStartable import com.android.systemui.keyboard.KeyboardUI import com.android.systemui.keyboard.PhysicalKeyboardCoreStartable import com.android.systemui.keyguard.KeyguardViewConfigurator @@ -257,6 +258,13 @@ abstract class SystemUICoreStartableModule { @Binds @IntoMap + @ClassKey(KeyboardTouchpadOobeTutorialCoreStartable::class) + abstract fun bindOobeSchedulerCoreStartable( + listener: KeyboardTouchpadOobeTutorialCoreStartable + ): CoreStartable + + @Binds + @IntoMap @ClassKey(PhysicalKeyboardCoreStartable::class) abstract fun bindKeyboardCoreStartable(listener: PhysicalKeyboardCoreStartable): CoreStartable diff --git a/packages/SystemUI/src/com/android/systemui/dagger/SystemUIModule.java b/packages/SystemUI/src/com/android/systemui/dagger/SystemUIModule.java index 1771f4dc8572..a44807248d23 100644 --- a/packages/SystemUI/src/com/android/systemui/dagger/SystemUIModule.java +++ b/packages/SystemUI/src/com/android/systemui/dagger/SystemUIModule.java @@ -80,6 +80,7 @@ import com.android.systemui.model.SceneContainerPlugin; import com.android.systemui.model.SysUiState; import com.android.systemui.motiontool.MotionToolModule; import com.android.systemui.navigationbar.NavigationBarComponent; +import com.android.systemui.navigationbar.gestural.dagger.GestureModule; import com.android.systemui.notetask.NoteTaskModule; import com.android.systemui.people.PeopleModule; import com.android.systemui.plugins.BcSmartspaceConfigPlugin; @@ -143,6 +144,7 @@ import com.android.systemui.statusbar.ui.binder.StatusBarViewBinderModule; import com.android.systemui.statusbar.window.StatusBarWindowModule; import com.android.systemui.telephony.data.repository.TelephonyRepositoryModule; import com.android.systemui.temporarydisplay.dagger.TemporaryDisplayModule; +import com.android.systemui.touchpad.TouchpadModule; import com.android.systemui.tuner.dagger.TunerModule; import com.android.systemui.user.UserModule; import com.android.systemui.user.domain.UserDomainLayerModule; @@ -215,6 +217,7 @@ import javax.inject.Named; FlagsModule.class, FlagDependenciesModule.class, FooterActionsModule.class, + GestureModule.class, InputMethodModule.class, KeyEventRepositoryModule.class, KeyboardModule.class, @@ -257,6 +260,7 @@ import javax.inject.Named; CommonSystemUIUnfoldModule.class, TelephonyRepositoryModule.class, TemporaryDisplayModule.class, + TouchpadModule.class, TunerModule.class, UserDomainLayerModule.class, UserModule.class, diff --git a/packages/SystemUI/src/com/android/systemui/doze/AlwaysOnDisplayPolicy.java b/packages/SystemUI/src/com/android/systemui/doze/AlwaysOnDisplayPolicy.java index e182d0b224fc..f80e0bece7cb 100644 --- a/packages/SystemUI/src/com/android/systemui/doze/AlwaysOnDisplayPolicy.java +++ b/packages/SystemUI/src/com/android/systemui/doze/AlwaysOnDisplayPolicy.java @@ -57,21 +57,29 @@ public class AlwaysOnDisplayPolicy { /** - * Integer used to dim the screen while dozing. + * Integer in the scale [1, 255] used to dim the screen while dozing. * * @see R.integer.config_screenBrightnessDoze */ public int defaultDozeBrightness; /** - * Integer used to dim the screen just before the screen turns off. + * Integer in the scale [1, 255] used to dim the screen just before the screen turns off. * * @see R.integer.config_screenBrightnessDim */ public int dimBrightness; /** - * Integer array to map ambient brightness type to real screen brightness. + * Float in the scale [0, 1] used to dim the screen just before the screen turns off. + * + * @see R.integer.config_screenBrightnessDimFloat + */ + public float dimBrightnessFloat; + + /** + * Integer array to map ambient brightness type to real screen brightness in the integer scale + * [1, 255]. * * @see Settings.Global#ALWAYS_ON_DISPLAY_CONSTANTS * @see #KEY_SCREEN_BRIGHTNESS_ARRAY @@ -189,6 +197,8 @@ public class AlwaysOnDisplayPolicy { com.android.internal.R.integer.config_screenBrightnessDoze); dimBrightness = resources.getInteger( com.android.internal.R.integer.config_screenBrightnessDim); + dimBrightnessFloat = resources.getFloat( + com.android.internal.R.dimen.config_screenBrightnessDimFloat); screenBrightnessArray = mParser.getIntArray(KEY_SCREEN_BRIGHTNESS_ARRAY, resources.getIntArray( R.array.config_doze_brightness_sensor_to_brightness)); diff --git a/packages/SystemUI/src/com/android/systemui/doze/DozeBrightnessHostForwarder.java b/packages/SystemUI/src/com/android/systemui/doze/DozeBrightnessHostForwarder.java index cf0dcad5bf0d..0b336143c34a 100644 --- a/packages/SystemUI/src/com/android/systemui/doze/DozeBrightnessHostForwarder.java +++ b/packages/SystemUI/src/com/android/systemui/doze/DozeBrightnessHostForwarder.java @@ -36,4 +36,10 @@ public class DozeBrightnessHostForwarder extends DozeMachine.Service.Delegate { super.setDozeScreenBrightness(brightness); mHost.setDozeScreenBrightness(brightness); } + + @Override + public void setDozeScreenBrightnessFloat(float brightness) { + super.setDozeScreenBrightnessFloat(brightness); + mHost.setDozeScreenBrightnessFloat(brightness); + } } diff --git a/packages/SystemUI/src/com/android/systemui/doze/DozeHost.java b/packages/SystemUI/src/com/android/systemui/doze/DozeHost.java index 17b455d7ef6f..2e7a459b0e9b 100644 --- a/packages/SystemUI/src/com/android/systemui/doze/DozeHost.java +++ b/packages/SystemUI/src/com/android/systemui/doze/DozeHost.java @@ -71,11 +71,17 @@ public interface DozeHost { /** * Sets the actual display brightness. - * @param value from 0 to 255. + * @param value from 1 to 255. */ void setDozeScreenBrightness(int value); /** + * Sets the actual display brightness. + * @param value from {@link PowerManager#BRIGHTNESS_MIN} to {@link PowerManager#BRIGHTNESS_MAX}. + */ + void setDozeScreenBrightnessFloat(float value); + + /** * Fade out screen before switching off the display power mode. * @param onDisplayOffCallback Executed when the display is black. */ diff --git a/packages/SystemUI/src/com/android/systemui/doze/DozeLog.java b/packages/SystemUI/src/com/android/systemui/doze/DozeLog.java index 9a9e698e0138..5bfcc975d02d 100644 --- a/packages/SystemUI/src/com/android/systemui/doze/DozeLog.java +++ b/packages/SystemUI/src/com/android/systemui/doze/DozeLog.java @@ -401,13 +401,22 @@ public class DozeLog implements Dumpable { /** * Appends new AOD screen brightness to logs - * @param brightness display brightness setting + * @param brightness display brightness setting between 1 and 255 */ public void traceDozeScreenBrightness(int brightness) { mLogger.logDozeScreenBrightness(brightness); } /** + * Appends new AOD screen brightness to logs + * @param brightness display brightness setting between {@link PowerManager#BRIGHTNESS_MIN} and + * {@link PowerManager#BRIGHTNESS_MAX} + */ + public void traceDozeScreenBrightnessFloat(float brightness) { + mLogger.logDozeScreenBrightnessFloat(brightness); + } + + /** * Appends new AOD dimming scrim opacity to logs * @param scrimOpacity */ diff --git a/packages/SystemUI/src/com/android/systemui/doze/DozeLogger.kt b/packages/SystemUI/src/com/android/systemui/doze/DozeLogger.kt index 9d6693efffa3..a31dbec242fe 100644 --- a/packages/SystemUI/src/com/android/systemui/doze/DozeLogger.kt +++ b/packages/SystemUI/src/com/android/systemui/doze/DozeLogger.kt @@ -309,7 +309,15 @@ class DozeLogger @Inject constructor( buffer.log(TAG, INFO, { int1 = brightness }, { - "Doze screen brightness set, brightness=$int1" + "Doze screen brightness set (int), brightness=$int1" + }) + } + + fun logDozeScreenBrightnessFloat(brightness: Float) { + buffer.log(TAG, INFO, { + double1 = brightness.toDouble() + }, { + "Doze screen brightness set (float), brightness=$double1" }) } diff --git a/packages/SystemUI/src/com/android/systemui/doze/DozeMachine.java b/packages/SystemUI/src/com/android/systemui/doze/DozeMachine.java index 7f0b16bca8b4..8198ef41bb49 100644 --- a/packages/SystemUI/src/com/android/systemui/doze/DozeMachine.java +++ b/packages/SystemUI/src/com/android/systemui/doze/DozeMachine.java @@ -507,9 +507,13 @@ public class DozeMachine { /** Request waking up. */ void requestWakeUp(@DozeLog.Reason int reason); - /** Set screen brightness */ + /** Set screen brightness between 1 and 255 */ void setDozeScreenBrightness(int brightness); + /** Set screen brightness between {@link PowerManager#BRIGHTNESS_MIN} and + * {@link PowerManager#BRIGHTNESS_MAX} */ + void setDozeScreenBrightnessFloat(float brightness); + class Delegate implements Service { private final Service mDelegate; private final Executor mBgExecutor; @@ -540,6 +544,13 @@ public class DozeMachine { mDelegate.setDozeScreenBrightness(brightness); }); } + + @Override + public void setDozeScreenBrightnessFloat(float brightness) { + mBgExecutor.execute(() -> { + mDelegate.setDozeScreenBrightnessFloat(brightness); + }); + } } } } diff --git a/packages/SystemUI/src/com/android/systemui/doze/DozeScreenBrightness.java b/packages/SystemUI/src/com/android/systemui/doze/DozeScreenBrightness.java index 323ed9871dc3..6ed84e573d7c 100644 --- a/packages/SystemUI/src/com/android/systemui/doze/DozeScreenBrightness.java +++ b/packages/SystemUI/src/com/android/systemui/doze/DozeScreenBrightness.java @@ -20,6 +20,8 @@ import static android.os.PowerManager.GO_TO_SLEEP_REASON_TIMEOUT; import static com.android.systemui.keyguard.WakefulnessLifecycle.WAKEFULNESS_GOING_TO_SLEEP; +import android.annotation.Nullable; +import android.annotation.SuppressLint; import android.content.BroadcastReceiver; import android.content.Context; import android.content.Intent; @@ -27,6 +29,7 @@ import android.hardware.Sensor; import android.hardware.SensorEvent; import android.hardware.SensorEventListener; import android.hardware.SensorManager; +import android.hardware.display.DisplayManager; import android.os.Handler; import android.os.PowerManager; import android.os.SystemProperties; @@ -34,6 +37,7 @@ import android.os.Trace; import android.os.UserHandle; import android.provider.Settings; import android.util.IndentingPrintWriter; +import android.view.Display; import com.android.internal.R; import com.android.systemui.doze.dagger.BrightnessSensor; @@ -46,6 +50,7 @@ import com.android.systemui.util.sensors.AsyncSensorManager; import com.android.systemui.util.settings.SystemSettings; import java.io.PrintWriter; +import java.util.Arrays; import java.util.Objects; import java.util.Optional; @@ -74,6 +79,7 @@ public class DozeScreenBrightness extends BroadcastReceiver implements DozeMachi private final DozeHost mDozeHost; private final Handler mHandler; private final SensorManager mSensorManager; + private final DisplayManager mDisplayManager; private final Optional<Sensor>[] mLightSensorOptional; // light sensors to use per posture private final WakefulnessLifecycle mWakefulnessLifecycle; private final DozeParameters mDozeParameters; @@ -81,13 +87,17 @@ public class DozeScreenBrightness extends BroadcastReceiver implements DozeMachi private final DozeLog mDozeLog; private final SystemSettings mSystemSettings; private final int[] mSensorToBrightness; + @Nullable + private final float[] mSensorToBrightnessFloat; private final int[] mSensorToScrimOpacity; private final int mScreenBrightnessDim; + private final float mScreenBrightnessDimFloat; @DevicePostureController.DevicePostureInt private int mDevicePosture; private boolean mRegistered; private int mDefaultDozeBrightness; + private float mDefaultDozeBrightnessFloat; private boolean mPaused = false; private boolean mScreenOff = false; private int mLastSensorValue = -1; @@ -102,6 +112,7 @@ public class DozeScreenBrightness extends BroadcastReceiver implements DozeMachi private int mDebugBrightnessBucket = -1; @Inject + @SuppressLint("AndroidFrameworkRequiresPermission") public DozeScreenBrightness( Context context, @WrappedService DozeMachine.Service service, @@ -113,10 +124,12 @@ public class DozeScreenBrightness extends BroadcastReceiver implements DozeMachi DozeParameters dozeParameters, DevicePostureController devicePostureController, DozeLog dozeLog, - SystemSettings systemSettings) { + SystemSettings systemSettings, + DisplayManager displayManager) { mContext = context; mDozeService = service; mSensorManager = sensorManager; + mDisplayManager = displayManager; mLightSensorOptional = lightSensorOptional; mDevicePostureController = devicePostureController; mDevicePosture = mDevicePostureController.getDevicePosture(); @@ -131,8 +144,13 @@ public class DozeScreenBrightness extends BroadcastReceiver implements DozeMachi R.dimen.config_screenBrightnessMinimumDimAmountFloat); mDefaultDozeBrightness = alwaysOnDisplayPolicy.defaultDozeBrightness; + mDefaultDozeBrightnessFloat = + mDisplayManager.getDefaultDozeBrightness(mContext.getDisplayId()); mScreenBrightnessDim = alwaysOnDisplayPolicy.dimBrightness; + mScreenBrightnessDimFloat = alwaysOnDisplayPolicy.dimBrightnessFloat; mSensorToBrightness = alwaysOnDisplayPolicy.screenBrightnessArray; + mSensorToBrightnessFloat = + mDisplayManager.getDozeBrightnessSensorValueToBrightness(mContext.getDisplayId()); mSensorToScrimOpacity = alwaysOnDisplayPolicy.dimmingScrimArray; mDevicePostureController.addCallback(mDevicePostureCallback); @@ -193,11 +211,22 @@ public class DozeScreenBrightness extends BroadcastReceiver implements DozeMachi if (force || mRegistered || mDebugBrightnessBucket != -1) { int sensorValue = mDebugBrightnessBucket == -1 ? mLastSensorValue : mDebugBrightnessBucket; - int brightness = computeBrightness(sensorValue); - boolean brightnessReady = brightness > 0; - if (brightnessReady) { - mDozeService.setDozeScreenBrightness( - clampToDimBrightnessForScreenOff(clampToUserSetting(brightness))); + boolean brightnessReady; + if (shouldUseFloatBrightness()) { + float brightness = computeBrightnessFloat(sensorValue); + brightnessReady = brightness >= 0; + if (brightnessReady) { + mDozeService.setDozeScreenBrightnessFloat( + clampToDimBrightnessForScreenOffFloat( + clampToUserSettingFloat(brightness))); + } + } else { + int brightness = computeBrightness(sensorValue); + brightnessReady = brightness > 0; + if (brightnessReady) { + mDozeService.setDozeScreenBrightness( + clampToDimBrightnessForScreenOff(clampToUserSetting(brightness))); + } } int scrimOpacity = -1; @@ -249,17 +278,30 @@ public class DozeScreenBrightness extends BroadcastReceiver implements DozeMachi return mSensorToBrightness[sensorValue]; } + private float computeBrightnessFloat(int sensorValue) { + if (sensorValue < 0 || sensorValue >= mSensorToBrightnessFloat.length) { + return -1; + } + return mSensorToBrightnessFloat[sensorValue]; + } + @Override public void onAccuracyChanged(Sensor sensor, int accuracy) { } private void resetBrightnessToDefault() { - mDozeService.setDozeScreenBrightness( - clampToDimBrightnessForScreenOff( - clampToUserSetting(mDefaultDozeBrightness))); + if (shouldUseFloatBrightness()) { + mDozeService.setDozeScreenBrightnessFloat( + clampToDimBrightnessForScreenOffFloat( + clampToUserSettingFloat(mDefaultDozeBrightnessFloat))); + } else { + mDozeService.setDozeScreenBrightness( + clampToDimBrightnessForScreenOff( + clampToUserSetting(mDefaultDozeBrightness))); + } mDozeHost.setAodDimmingScrim(0f); } - //TODO: brightnessfloat change usages to float. + private int clampToUserSetting(int brightness) { int screenBrightnessModeSetting = mSystemSettings.getIntForUser( Settings.System.SCREEN_BRIGHTNESS_MODE, @@ -274,6 +316,19 @@ public class DozeScreenBrightness extends BroadcastReceiver implements DozeMachi return Math.min(brightness, userSetting); } + @SuppressLint("AndroidFrameworkRequiresPermission") + private float clampToUserSettingFloat(float brightness) { + int screenBrightnessModeSetting = mSystemSettings.getIntForUser( + Settings.System.SCREEN_BRIGHTNESS_MODE, + Settings.System.SCREEN_BRIGHTNESS_MODE_MANUAL, UserHandle.USER_CURRENT); + if (screenBrightnessModeSetting == Settings.System.SCREEN_BRIGHTNESS_MODE_AUTOMATIC) { + return brightness; + } + + float userSetting = mDisplayManager.getBrightness(Display.DEFAULT_DISPLAY); + return Math.min(brightness, userSetting); + } + /** * Clamp the brightness to the dim brightness value used by PowerManagerService just before the * device times out and goes to sleep, if we are sleeping from a timeout. This ensures that we @@ -301,6 +356,31 @@ public class DozeScreenBrightness extends BroadcastReceiver implements DozeMachi } } + /** + * Clamp the brightness to the dim brightness value used by PowerManagerService just before the + * device times out and goes to sleep, if we are sleeping from a timeout. This ensures that we + * don't raise the brightness back to the user setting before or during the screen off + * animation. + */ + private float clampToDimBrightnessForScreenOffFloat(float brightness) { + final boolean screenTurningOff = + (mDozeParameters.shouldClampToDimBrightness() + || mWakefulnessLifecycle.getWakefulness() == WAKEFULNESS_GOING_TO_SLEEP) + && mState == DozeMachine.State.INITIALIZED; + if (screenTurningOff + && mWakefulnessLifecycle.getLastSleepReason() == GO_TO_SLEEP_REASON_TIMEOUT) { + return Math.max( + PowerManager.BRIGHTNESS_MIN, + // Use the lower of either the dim brightness, or the current brightness reduced + // by the minimum dim amount. This is the same logic used in + // DisplayPowerController#updatePowerState to apply a minimum dim amount. + Math.min(brightness - mScreenBrightnessMinimumDimAmountFloat, + mScreenBrightnessDimFloat)); + } else { + return brightness; + } + } + private void setLightSensorEnabled(boolean enabled) { if (enabled && !mRegistered && isLightSensorPresent()) { // Wait until we get an event from the sensor until indicating ready. @@ -342,6 +422,20 @@ public class DozeScreenBrightness extends BroadcastReceiver implements DozeMachi idpw.increaseIndent(); idpw.println("registered=" + mRegistered); idpw.println("posture=" + DevicePostureController.devicePostureToString(mDevicePosture)); + idpw.println("sensorToBrightness=" + Arrays.toString(mSensorToBrightness)); + idpw.println("sensorToBrightnessFloat=" + Arrays.toString(mSensorToBrightnessFloat)); + idpw.println("sensorToScrimOpacity=" + Arrays.toString(mSensorToScrimOpacity)); + idpw.println("screenBrightnessDim=" + mScreenBrightnessDim); + idpw.println("screenBrightnessDimFloat=" + mScreenBrightnessDimFloat); + idpw.println("mDefaultDozeBrightness=" + mDefaultDozeBrightness); + idpw.println("mDefaultDozeBrightnessFloat=" + mDefaultDozeBrightnessFloat); + idpw.println("mLastSensorValue=" + mLastSensorValue); + idpw.println("shouldUseFloatBrightness()=" + shouldUseFloatBrightness()); + } + + private boolean shouldUseFloatBrightness() { + return com.android.server.display.feature.flags.Flags.dozeBrightnessFloat() + && mSensorToBrightnessFloat != null; } private final DevicePostureController.Callback mDevicePostureCallback = diff --git a/packages/SystemUI/src/com/android/systemui/dreams/DreamOverlayService.java b/packages/SystemUI/src/com/android/systemui/dreams/DreamOverlayService.java index 982398579477..931066d5c582 100644 --- a/packages/SystemUI/src/com/android/systemui/dreams/DreamOverlayService.java +++ b/packages/SystemUI/src/com/android/systemui/dreams/DreamOverlayService.java @@ -27,7 +27,9 @@ import static com.android.systemui.util.kotlin.JavaAdapterKt.collectFlow; import android.content.ComponentName; import android.content.Context; import android.content.Intent; +import android.content.pm.ActivityInfo; import android.graphics.drawable.ColorDrawable; +import android.service.dreams.DreamActivity; import android.util.Log; import android.view.View; import android.view.ViewGroup; @@ -63,6 +65,7 @@ import com.android.systemui.complication.dagger.ComplicationComponent; import com.android.systemui.dagger.qualifiers.Main; import com.android.systemui.dreams.dagger.DreamOverlayComponent; import com.android.systemui.keyguard.domain.interactor.KeyguardInteractor; +import com.android.systemui.navigationbar.gestural.domain.GestureInteractor; import com.android.systemui.shade.ShadeExpansionChangeEvent; import com.android.systemui.touch.TouchInsetManager; import com.android.systemui.util.concurrency.DelayableExecutor; @@ -135,6 +138,8 @@ public class DreamOverlayService extends android.service.dreams.DreamOverlayServ private final DreamOverlayComponent mDreamOverlayComponent; + private ComponentName mCurrentBlockedGestureDreamActivityComponent; + /** * This {@link LifecycleRegistry} controls when dream overlay functionality, like touch * handling, should be active. It will automatically be paused when the dream overlay is hidden @@ -222,6 +227,8 @@ public class DreamOverlayService extends android.service.dreams.DreamOverlayServ private final DreamOverlayStateController mStateController; + private final GestureInteractor mGestureInteractor; + @VisibleForTesting public enum DreamOverlayEvent implements UiEventLogger.UiEventEnum { @UiEvent(doc = "The dream overlay has entered start.") @@ -265,6 +272,7 @@ public class DreamOverlayService extends android.service.dreams.DreamOverlayServ ComponentName homeControlPanelDreamComponent, DreamOverlayCallbackController dreamOverlayCallbackController, KeyguardInteractor keyguardInteractor, + GestureInteractor gestureInteractor, @Named(DREAM_OVERLAY_WINDOW_TITLE) String windowTitle) { super(executor); mContext = context; @@ -281,6 +289,7 @@ public class DreamOverlayService extends android.service.dreams.DreamOverlayServ mWindowTitle = windowTitle; mCommunalInteractor = communalInteractor; mSystemDialogsCloser = systemDialogsCloser; + mGestureInteractor = gestureInteractor; final ViewModelStore viewModelStore = new ViewModelStore(); final Complication.Host host = @@ -391,6 +400,7 @@ public class DreamOverlayService extends android.service.dreams.DreamOverlayServ mStarted = true; updateRedirectWakeup(); + updateBlockedGestureDreamActivityComponent(); } private void updateRedirectWakeup() { @@ -401,6 +411,18 @@ public class DreamOverlayService extends android.service.dreams.DreamOverlayServ redirectWake(mCommunalAvailable && !glanceableHubAllowKeyguardWhenDreaming()); } + private void updateBlockedGestureDreamActivityComponent() { + // TODO(b/343815446): We should not be crafting this ActivityInfo ourselves. It should be + // in a common place, Such as DreamActivity itself. + final ActivityInfo info = new ActivityInfo(); + info.name = DreamActivity.class.getName(); + info.packageName = getDreamComponent().getPackageName(); + mCurrentBlockedGestureDreamActivityComponent = info.getComponentName(); + + mGestureInteractor.addGestureBlockedActivity(mCurrentBlockedGestureDreamActivityComponent, + GestureInteractor.Scope.Global); + } + @Override public void onEndDream() { resetCurrentDreamOverlayLocked(); @@ -472,6 +494,7 @@ public class DreamOverlayService extends android.service.dreams.DreamOverlayServ * into the dream window. */ private boolean addOverlayWindowLocked(WindowManager.LayoutParams layoutParams) { + mWindow = new PhoneWindow(mContext); // Default to SystemUI name for TalkBack. mWindow.setTitle(mWindowTitle); @@ -554,6 +577,14 @@ public class DreamOverlayService extends android.service.dreams.DreamOverlayServ } mWindow = null; + + // Always unregister the any set DreamActivity from being blocked from gestures. + if (mCurrentBlockedGestureDreamActivityComponent != null) { + mGestureInteractor.removeGestureBlockedActivity( + mCurrentBlockedGestureDreamActivityComponent, GestureInteractor.Scope.Global); + mCurrentBlockedGestureDreamActivityComponent = null; + } + mStarted = false; } } diff --git a/packages/SystemUI/src/com/android/systemui/flags/FlagDependencies.kt b/packages/SystemUI/src/com/android/systemui/flags/FlagDependencies.kt index 0e06117b2693..6e4038d85e03 100644 --- a/packages/SystemUI/src/com/android/systemui/flags/FlagDependencies.kt +++ b/packages/SystemUI/src/com/android/systemui/flags/FlagDependencies.kt @@ -40,6 +40,7 @@ import com.android.systemui.statusbar.notification.shared.NotificationIconContai import com.android.systemui.statusbar.notification.shared.NotificationMinimalismPrototype import com.android.systemui.statusbar.notification.shared.NotificationsHeadsUpRefactor import com.android.systemui.statusbar.notification.shared.NotificationsLiveDataStoreRefactor +import com.android.systemui.statusbar.notification.shared.NotificationThrottleHun import com.android.systemui.statusbar.notification.shared.PriorityPeopleSection import javax.inject.Inject @@ -51,6 +52,7 @@ class FlagDependencies @Inject constructor(featureFlags: FeatureFlagsClassic, ha // Internal notification backend dependencies crossAppPoliteNotifications dependsOn politeNotifications vibrateWhileUnlockedToken dependsOn politeNotifications + modesUi dependsOn modesApi // Internal notification frontend dependencies NotificationsLiveDataStoreRefactor.token dependsOn NotificationIconContainerRefactor.token @@ -58,6 +60,7 @@ class FlagDependencies @Inject constructor(featureFlags: FeatureFlagsClassic, ha NotificationAvalancheSuppression.token dependsOn VisualInterruptionRefactor.token PriorityPeopleSection.token dependsOn SortBySectionTimeFlag.token NotificationMinimalismPrototype.token dependsOn NotificationsHeadsUpRefactor.token + NotificationsHeadsUpRefactor.token dependsOn NotificationThrottleHun.token // SceneContainer dependencies SceneContainerFlag.getFlagDependencies().forEach { (alpha, beta) -> alpha dependsOn beta } @@ -85,6 +88,12 @@ class FlagDependencies @Inject constructor(featureFlags: FeatureFlagsClassic, ha private inline val vibrateWhileUnlockedToken: FlagToken get() = FlagToken(FLAG_VIBRATE_WHILE_UNLOCKED, vibrateWhileUnlocked()) + private inline val modesUi + get() = FlagToken(android.app.Flags.FLAG_MODES_UI, android.app.Flags.modesUi()) + + private inline val modesApi + get() = FlagToken(android.app.Flags.FLAG_MODES_API, android.app.Flags.modesApi()) + private inline val communalHub get() = FlagToken(FLAG_COMMUNAL_HUB, communalHub()) } diff --git a/packages/SystemUI/src/com/android/systemui/haptics/qs/QSLongPressEffect.kt b/packages/SystemUI/src/com/android/systemui/haptics/qs/QSLongPressEffect.kt index 491c73d0ae56..4652b2a30eb4 100644 --- a/packages/SystemUI/src/com/android/systemui/haptics/qs/QSLongPressEffect.kt +++ b/packages/SystemUI/src/com/android/systemui/haptics/qs/QSLongPressEffect.kt @@ -26,7 +26,9 @@ import com.android.systemui.animation.DelegateTransitionAnimatorController import com.android.systemui.animation.DialogCuj import com.android.systemui.animation.DialogTransitionAnimator import com.android.systemui.animation.Expandable -import com.android.systemui.plugins.FalsingManager +import com.android.systemui.log.LogBuffer +import com.android.systemui.log.core.LogLevel +import com.android.systemui.log.dagger.QSLog import com.android.systemui.plugins.qs.QSTile import com.android.systemui.statusbar.VibratorHelper import com.android.systemui.statusbar.policy.KeyguardStateController @@ -48,7 +50,7 @@ class QSLongPressEffect constructor( private val vibratorHelper: VibratorHelper?, private val keyguardStateController: KeyguardStateController, - private val falsingManager: FalsingManager, + @QSLog private val logBuffer: LogBuffer, ) { var effectDuration = 0 @@ -103,6 +105,7 @@ constructor( } fun handleActionDown() { + logEvent(qsTile?.tileSpec, state, "action down received") when (state) { State.IDLE -> { setState(State.TIMEOUT_WAIT) @@ -114,6 +117,7 @@ constructor( } fun handleActionUp() { + logEvent(qsTile?.tileSpec, state, "action up received") if (state == State.RUNNING_FORWARD) { setState(State.RUNNING_BACKWARDS_FROM_UP) callback?.onReverseAnimator() @@ -132,6 +136,7 @@ constructor( } fun handleAnimationStart() { + logEvent(qsTile?.tileSpec, state, "animation started") if (state == State.TIMEOUT_WAIT) { vibrate(longPressHint) setState(State.RUNNING_FORWARD) @@ -140,6 +145,7 @@ constructor( /** This function is called both when an animator completes or gets cancelled */ fun handleAnimationComplete() { + logEvent(qsTile?.tileSpec, state, "animation completed") when (state) { State.RUNNING_FORWARD -> { vibrate(snapEffect) @@ -149,11 +155,13 @@ constructor( callback?.onResetProperties() setState(State.IDLE) } + logEvent(qsTile?.tileSpec, state, "long click action triggered") qsTile?.longClick(expandable) } State.RUNNING_BACKWARDS_FROM_UP -> { callback?.onEffectFinishedReversing() setState(getStateForClick()) + logEvent(qsTile?.tileSpec, state, "click action triggered") qsTile?.click(expandable) } State.RUNNING_BACKWARDS_FROM_CANCEL -> { @@ -181,6 +189,7 @@ constructor( if (keyguardStateController.isPrimaryBouncerShowing || !isStateClickable) return false setState(getStateForClick()) + logEvent(qsTile?.tileSpec, state, "click action triggered") qsTile?.click(expandable) return true } @@ -195,11 +204,8 @@ constructor( @VisibleForTesting fun getStateForClick(): State { val isTileUnavailable = qsTile?.state?.state == Tile.STATE_UNAVAILABLE - val isFalseTapWhileLocked = - !keyguardStateController.isUnlocked && - falsingManager.isFalseTap(FalsingManager.LOW_PENALTY) val handlesLongClick = qsTile?.state?.handlesLongClick == true - return if (isTileUnavailable || isFalseTapWhileLocked || !handlesLongClick) { + return if (isTileUnavailable || !handlesLongClick || keyguardStateController.isShowing) { // The click event will not perform an action that resets the state. Therefore, this is // the last opportunity to reset the state back to IDLE. State.IDLE @@ -278,6 +284,20 @@ constructor( return delegated } + private fun logEvent(tileSpec: String?, state: State, event: String) { + if (!DEBUG) return + logBuffer.log( + TAG, + LogLevel.DEBUG, + { + str1 = tileSpec + str2 = event + str3 = state.name + }, + { "[long-press effect on $str1 tile] $str2 on state: $str3" } + ) + } + enum class State { IDLE, /* The effect is idle waiting for touch input */ TIMEOUT_WAIT, /* The effect is waiting for a tap timeout period */ @@ -309,4 +329,9 @@ constructor( /** Cancel the effect animator */ fun onCancelAnimator() } + + companion object { + private const val TAG = "QSLongPressEffect" + private const val DEBUG = true + } } diff --git a/packages/SystemUI/src/com/android/systemui/inputdevice/data/repository/InputDeviceRepository.kt b/packages/SystemUI/src/com/android/systemui/inputdevice/data/repository/InputDeviceRepository.kt index 3b161b659af9..5a008bddc748 100644 --- a/packages/SystemUI/src/com/android/systemui/inputdevice/data/repository/InputDeviceRepository.kt +++ b/packages/SystemUI/src/com/android/systemui/inputdevice/data/repository/InputDeviceRepository.kt @@ -45,7 +45,7 @@ constructor( data class DeviceAdded(val deviceId: Int) : DeviceChange - data object DeviceRemoved : DeviceChange + data class DeviceRemoved(val deviceId: Int) : DeviceChange data object FreshStart : DeviceChange @@ -72,7 +72,7 @@ constructor( override fun onInputDeviceRemoved(deviceId: Int) { connectedDevices = connectedDevices - deviceId - sendWithLogging(connectedDevices to DeviceRemoved) + sendWithLogging(connectedDevices to DeviceRemoved(deviceId)) } } sendWithLogging(connectedDevices to FreshStart) diff --git a/packages/SystemUI/src/com/android/systemui/inputdevice/oobe/KeyboardTouchpadOobeTutorialCoreStartable.kt b/packages/SystemUI/src/com/android/systemui/inputdevice/oobe/KeyboardTouchpadOobeTutorialCoreStartable.kt new file mode 100644 index 000000000000..dbfea7688e0d --- /dev/null +++ b/packages/SystemUI/src/com/android/systemui/inputdevice/oobe/KeyboardTouchpadOobeTutorialCoreStartable.kt @@ -0,0 +1,37 @@ +/* + * Copyright (C) 2024 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.android.systemui.inputdevice.oobe + +import com.android.systemui.CoreStartable +import com.android.systemui.dagger.SysUISingleton +import com.android.systemui.inputdevice.oobe.domain.interactor.OobeTutorialSchedulerInteractor +import com.android.systemui.shared.Flags.newTouchpadGesturesTutorial +import dagger.Lazy +import javax.inject.Inject + +/** A [CoreStartable] to launch a scheduler for keyboard and touchpad OOBE education */ +@SysUISingleton +class KeyboardTouchpadOobeTutorialCoreStartable +@Inject +constructor(private val oobeTutorialSchedulerInteractor: Lazy<OobeTutorialSchedulerInteractor>) : + CoreStartable { + override fun start() { + if (newTouchpadGesturesTutorial()) { + oobeTutorialSchedulerInteractor.get().start() + } + } +} diff --git a/packages/SystemUI/src/com/android/systemui/inputdevice/oobe/domain/interactor/OobeTutorialSchedulerInteractor.kt b/packages/SystemUI/src/com/android/systemui/inputdevice/oobe/domain/interactor/OobeTutorialSchedulerInteractor.kt new file mode 100644 index 000000000000..0d69081adfa4 --- /dev/null +++ b/packages/SystemUI/src/com/android/systemui/inputdevice/oobe/domain/interactor/OobeTutorialSchedulerInteractor.kt @@ -0,0 +1,58 @@ +/* + * Copyright (C) 2024 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.android.systemui.inputdevice.oobe.domain.interactor + +import android.content.Context +import android.content.Intent +import com.android.systemui.dagger.SysUISingleton +import com.android.systemui.dagger.qualifiers.Application +import com.android.systemui.keyboard.data.repository.KeyboardRepository +import com.android.systemui.touchpad.data.repository.TouchpadRepository +import javax.inject.Inject +import kotlinx.coroutines.CoroutineScope +import kotlinx.coroutines.launch + +/** When keyboards or touchpads are connected, schedule a tutorial after given time has elapsed */ +@SysUISingleton +class OobeTutorialSchedulerInteractor +@Inject +constructor( + @Application private val context: Context, + @Application private val applicationScope: CoroutineScope, + keyboardRepository: KeyboardRepository, + touchpadRepository: TouchpadRepository +) { + private val isAnyKeyboardConnected = keyboardRepository.isAnyKeyboardConnected + private val isAnyTouchpadConnected = touchpadRepository.isAnyTouchpadConnected + + fun start() { + applicationScope.launch { isAnyKeyboardConnected.collect { startOobe() } } + applicationScope.launch { isAnyTouchpadConnected.collect { startOobe() } } + } + + private fun startOobe() { + val intent = Intent(TUTORIAL_ACTION) + intent.addCategory(Intent.CATEGORY_DEFAULT) + intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK) + context.startActivity(intent) + } + + companion object { + const val TAG = "OobeSchedulerInteractor" + const val TUTORIAL_ACTION = "com.android.systemui.action.TOUCHPAD_TUTORIAL" + } +} diff --git a/packages/SystemUI/src/com/android/systemui/keyboard/data/repository/KeyboardRepository.kt b/packages/SystemUI/src/com/android/systemui/keyboard/data/repository/KeyboardRepository.kt index 817849c41297..b6543074cdef 100644 --- a/packages/SystemUI/src/com/android/systemui/keyboard/data/repository/KeyboardRepository.kt +++ b/packages/SystemUI/src/com/android/systemui/keyboard/data/repository/KeyboardRepository.kt @@ -41,6 +41,7 @@ import kotlinx.coroutines.flow.Flow import kotlinx.coroutines.flow.asFlow import kotlinx.coroutines.flow.distinctUntilChanged import kotlinx.coroutines.flow.emptyFlow +import kotlinx.coroutines.flow.filter import kotlinx.coroutines.flow.flatMapConcat import kotlinx.coroutines.flow.flowOf import kotlinx.coroutines.flow.flowOn @@ -78,9 +79,15 @@ constructor( ) : KeyboardRepository { private val keyboardsChange: Flow<Pair<Collection<Int>, DeviceChange>> = - inputDeviceRepository.deviceChange.map { (ids, change) -> - ids.filter { id -> isPhysicalFullKeyboard(id) } to change - } + inputDeviceRepository.deviceChange + .map { (ids, change) -> ids.filter { id -> isPhysicalFullKeyboard(id) } to change } + .filter { (_, change) -> + when (change) { + FreshStart -> true + is DeviceAdded -> isPhysicalFullKeyboard(change.deviceId) + is DeviceRemoved -> isPhysicalFullKeyboard(change.deviceId) + } + } @FlowPreview override val newlyConnectedKeyboard: Flow<Keyboard> = diff --git a/packages/SystemUI/src/com/android/systemui/keyboard/docking/binder/KeyboardDockingIndicationViewBinder.kt b/packages/SystemUI/src/com/android/systemui/keyboard/docking/binder/KeyboardDockingIndicationViewBinder.kt index f649be2432c6..b859cdc5dee5 100644 --- a/packages/SystemUI/src/com/android/systemui/keyboard/docking/binder/KeyboardDockingIndicationViewBinder.kt +++ b/packages/SystemUI/src/com/android/systemui/keyboard/docking/binder/KeyboardDockingIndicationViewBinder.kt @@ -20,6 +20,7 @@ import android.content.Context import android.graphics.Paint import android.graphics.PixelFormat import android.view.WindowManager +import com.android.app.viewcapture.ViewCaptureAwareWindowManager import com.android.systemui.dagger.SysUISingleton import com.android.systemui.dagger.qualifiers.Application import com.android.systemui.keyboard.docking.ui.KeyboardDockingIndicationView @@ -37,7 +38,7 @@ constructor( context: Context, @Application private val applicationScope: CoroutineScope, private val viewModel: KeyboardDockingIndicationViewModel, - private val windowManager: WindowManager + private val windowManager: ViewCaptureAwareWindowManager, ) { private val windowLayoutParams = diff --git a/packages/SystemUI/src/com/android/systemui/keyboard/shortcut/ui/composable/ShortcutHelper.kt b/packages/SystemUI/src/com/android/systemui/keyboard/shortcut/ui/composable/ShortcutHelper.kt index af755d302e74..58719fe85c21 100644 --- a/packages/SystemUI/src/com/android/systemui/keyboard/shortcut/ui/composable/ShortcutHelper.kt +++ b/packages/SystemUI/src/com/android/systemui/keyboard/shortcut/ui/composable/ShortcutHelper.kt @@ -24,6 +24,9 @@ import androidx.compose.animation.AnimatedVisibility import androidx.compose.animation.core.animateFloatAsState import androidx.compose.foundation.Image import androidx.compose.foundation.background +import androidx.compose.foundation.focusable +import androidx.compose.foundation.interaction.MutableInteractionSource +import androidx.compose.foundation.interaction.collectIsFocusedAsState import androidx.compose.foundation.layout.Arrangement import androidx.compose.foundation.layout.Box import androidx.compose.foundation.layout.BoxScope @@ -77,11 +80,16 @@ import androidx.compose.runtime.remember import androidx.compose.runtime.setValue import androidx.compose.ui.Alignment import androidx.compose.ui.Modifier +import androidx.compose.ui.draw.drawWithContent import androidx.compose.ui.focus.FocusRequester import androidx.compose.ui.focus.focusRequester +import androidx.compose.ui.geometry.CornerRadius +import androidx.compose.ui.geometry.Offset +import androidx.compose.ui.geometry.Rect import androidx.compose.ui.graphics.Color import androidx.compose.ui.graphics.RectangleShape import androidx.compose.ui.graphics.Shape +import androidx.compose.ui.graphics.drawscope.Stroke import androidx.compose.ui.graphics.graphicsLayer import androidx.compose.ui.input.nestedscroll.nestedScroll import androidx.compose.ui.platform.LocalContext @@ -100,6 +108,7 @@ import androidx.compose.ui.unit.sp import androidx.compose.ui.util.fastFirstOrNull import androidx.compose.ui.util.fastForEach import androidx.compose.ui.util.fastForEachIndexed +import androidx.compose.ui.zIndex import com.android.compose.ui.graphics.painter.rememberDrawablePainter import com.android.compose.windowsizeclass.LocalWindowSizeClass import com.android.systemui.keyboard.shortcut.shared.model.Shortcut @@ -405,7 +414,7 @@ private fun ShortcutHelperTwoPane( Row(Modifier.fillMaxWidth()) { StartSidePanel( onSearchQueryChanged = onSearchQueryChanged, - modifier = Modifier.fillMaxWidth(fraction = 0.32f), + modifier = Modifier.width(200.dp), categories = categories, onKeyboardSettingsClicked = onKeyboardSettingsClicked, selectedCategory = selectedCategoryType, @@ -462,7 +471,18 @@ private fun SubCategoryTitle(title: String) { @Composable private fun ShortcutView(modifier: Modifier, searchQuery: String, shortcut: Shortcut) { - Row(modifier) { + val interactionSource = remember { MutableInteractionSource() } + val isFocused by interactionSource.collectIsFocusedAsState() + Row( + modifier + .focusable(interactionSource = interactionSource) + .outlineFocusModifier( + isFocused = isFocused, + focusColor = MaterialTheme.colorScheme.secondary, + padding = 8.dp, + cornerRadius = 16.dp + ) + ) { Row( modifier = Modifier.width(128.dp).align(Alignment.CenterVertically), horizontalArrangement = Arrangement.spacedBy(16.dp), @@ -670,10 +690,23 @@ private fun CategoryItemTwoPane( colors: NavigationDrawerItemColors = NavigationDrawerItemDefaults.colors(unselectedContainerColor = Color.Transparent), ) { + val interactionSource = remember { MutableInteractionSource() } + val isFocused by interactionSource.collectIsFocusedAsState() + Surface( selected = selected, onClick = onClick, - modifier = Modifier.semantics { role = Role.Tab }.heightIn(min = 64.dp).fillMaxWidth(), + modifier = + Modifier.semantics { role = Role.Tab } + .heightIn(min = 64.dp) + .fillMaxWidth() + .focusable(interactionSource = interactionSource) + .outlineFocusModifier( + isFocused = isFocused, + focusColor = MaterialTheme.colorScheme.secondary, + padding = 2.dp, + cornerRadius = 33.dp + ), shape = RoundedCornerShape(28.dp), color = colors.containerColor(selected).value, ) { @@ -697,6 +730,39 @@ private fun CategoryItemTwoPane( } } +private fun Modifier.outlineFocusModifier( + isFocused: Boolean, + focusColor: Color, + padding: Dp, + cornerRadius: Dp +): Modifier { + if (isFocused) { + return this.drawWithContent { + val focusOutline = + Rect(Offset.Zero, size).let { + if (padding > 0.dp) { + it.inflate(padding.toPx()) + } else { + it.deflate(padding.unaryMinus().toPx()) + } + } + drawContent() + drawRoundRect( + color = focusColor, + style = Stroke(width = 3.dp.toPx()), + topLeft = focusOutline.topLeft, + size = focusOutline.size, + cornerRadius = CornerRadius(cornerRadius.toPx()) + ) + } + // Increasing Z-Index so focus outline is drawn on top of "selected" category + // background. + .zIndex(1f) + } else { + return this + } +} + @Composable @OptIn(ExperimentalMaterial3Api::class) private fun TitleBar() { diff --git a/packages/SystemUI/src/com/android/systemui/keyguard/DismissCallbackRegistry.java b/packages/SystemUI/src/com/android/systemui/keyguard/DismissCallbackRegistry.java index d1bbc3359917..0d01ee1b2cfa 100644 --- a/packages/SystemUI/src/com/android/systemui/keyguard/DismissCallbackRegistry.java +++ b/packages/SystemUI/src/com/android/systemui/keyguard/DismissCallbackRegistry.java @@ -16,6 +16,7 @@ package com.android.systemui.keyguard; +import android.util.Log; import com.android.internal.policy.IKeyguardDismissCallback; import com.android.systemui.dagger.SysUISingleton; import com.android.systemui.dagger.qualifiers.UiBackground; @@ -33,6 +34,7 @@ public class DismissCallbackRegistry { private final ArrayList<DismissCallbackWrapper> mDismissCallbacks = new ArrayList<>(); private final Executor mUiBgExecutor; + private final static String TAG = "DismissCallbackRegistry"; @Inject public DismissCallbackRegistry(@UiBackground Executor uiBgExecutor) { @@ -40,10 +42,12 @@ public class DismissCallbackRegistry { } public void addCallback(IKeyguardDismissCallback callback) { + Log.d(TAG, "Adding callback: " + callback); mDismissCallbacks.add(new DismissCallbackWrapper(callback)); } public void notifyDismissCancelled() { + Log.d(TAG, "notifyDismissCancelled(" + mDismissCallbacks.size() + ")"); for (int i = mDismissCallbacks.size() - 1; i >= 0; i--) { DismissCallbackWrapper callback = mDismissCallbacks.get(i); mUiBgExecutor.execute(callback::notifyDismissCancelled); @@ -52,6 +56,7 @@ public class DismissCallbackRegistry { } public void notifyDismissSucceeded() { + Log.d(TAG, "notifyDismissSucceeded(" + mDismissCallbacks.size() + ")"); for (int i = mDismissCallbacks.size() - 1; i >= 0; i--) { DismissCallbackWrapper callback = mDismissCallbacks.get(i); mUiBgExecutor.execute(callback::notifyDismissSucceeded); 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 ae751dbacd68..edf17c1e9e80 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 @@ -34,6 +34,7 @@ import com.android.systemui.dreams.DreamOverlayCallbackController import com.android.systemui.keyguard.shared.model.BiometricUnlockMode import com.android.systemui.keyguard.shared.model.BiometricUnlockModel import com.android.systemui.keyguard.shared.model.BiometricUnlockSource +import com.android.systemui.keyguard.shared.model.CameraLaunchSourceModel import com.android.systemui.keyguard.shared.model.DismissAction import com.android.systemui.keyguard.shared.model.DozeStateModel import com.android.systemui.keyguard.shared.model.DozeTransitionModel @@ -237,6 +238,9 @@ interface KeyguardRepository { /** Observable updated when keyguardDone should be called either now or soon. */ val keyguardDone: Flow<KeyguardDone> + /** Last camera launch detection event */ + val onCameraLaunchDetected: MutableStateFlow<CameraLaunchSourceModel> + /** * Emits after the keyguard is done animating away. * @@ -380,6 +384,8 @@ constructor( private val _keyguardAlpha = MutableStateFlow(1f) override val keyguardAlpha = _keyguardAlpha.asStateFlow() + override val onCameraLaunchDetected = MutableStateFlow(CameraLaunchSourceModel()) + override val panelAlpha: MutableStateFlow<Float> = MutableStateFlow(1f) private val _clockShouldBeCentered = MutableStateFlow(true) 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 index a915241fc646..ae830eed2c6b 100644 --- a/packages/SystemUI/src/com/android/systemui/keyguard/domain/interactor/FromAlternateBouncerTransitionInteractor.kt +++ b/packages/SystemUI/src/com/android/systemui/keyguard/domain/interactor/FromAlternateBouncerTransitionInteractor.kt @@ -198,7 +198,12 @@ constructor( interpolator = Interpolators.LINEAR duration = when (toState) { + KeyguardState.AOD -> TO_AOD_DURATION + KeyguardState.DOZING -> TO_DOZING_DURATION KeyguardState.GONE -> TO_GONE_DURATION + KeyguardState.LOCKSCREEN -> TO_LOCKSCREEN_DURATION + KeyguardState.OCCLUDED -> TO_OCCLUDED_DURATION + KeyguardState.PRIMARY_BOUNCER -> TO_PRIMARY_BOUNCER_DURATION else -> TRANSITION_DURATION_MS }.inWholeMilliseconds } @@ -211,10 +216,11 @@ constructor( companion object { const val TAG = "FromAlternateBouncerTransitionInteractor" val TRANSITION_DURATION_MS = 300.milliseconds - val TO_GONE_DURATION = 500.milliseconds val TO_AOD_DURATION = TRANSITION_DURATION_MS - val TO_PRIMARY_BOUNCER_DURATION = TRANSITION_DURATION_MS val TO_DOZING_DURATION = TRANSITION_DURATION_MS + val TO_GONE_DURATION = 500.milliseconds + val TO_LOCKSCREEN_DURATION = 300.milliseconds val TO_OCCLUDED_DURATION = TRANSITION_DURATION_MS + val TO_PRIMARY_BOUNCER_DURATION = TRANSITION_DURATION_MS } } diff --git a/packages/SystemUI/src/com/android/systemui/keyguard/domain/interactor/FromAodTransitionInteractor.kt b/packages/SystemUI/src/com/android/systemui/keyguard/domain/interactor/FromAodTransitionInteractor.kt index e5ccc4a14003..2a8bb471c217 100644 --- a/packages/SystemUI/src/com/android/systemui/keyguard/domain/interactor/FromAodTransitionInteractor.kt +++ b/packages/SystemUI/src/com/android/systemui/keyguard/domain/interactor/FromAodTransitionInteractor.kt @@ -220,7 +220,10 @@ constructor( interpolator = Interpolators.LINEAR duration = when (toState) { + KeyguardState.GONE -> TO_GONE_DURATION KeyguardState.LOCKSCREEN -> TO_LOCKSCREEN_DURATION + KeyguardState.OCCLUDED -> TO_OCCLUDED_DURATION + KeyguardState.PRIMARY_BOUNCER -> TO_PRIMARY_BOUNCER_DURATION else -> DEFAULT_DURATION }.inWholeMilliseconds } @@ -229,9 +232,9 @@ constructor( companion object { private const val TAG = "FromAodTransitionInteractor" private val DEFAULT_DURATION = 500.milliseconds - val TO_LOCKSCREEN_DURATION = 500.milliseconds val TO_GONE_DURATION = DEFAULT_DURATION - val TO_OCCLUDED_DURATION = DEFAULT_DURATION + val TO_LOCKSCREEN_DURATION = 500.milliseconds + val TO_OCCLUDED_DURATION = 550.milliseconds val TO_PRIMARY_BOUNCER_DURATION = DEFAULT_DURATION } } diff --git a/packages/SystemUI/src/com/android/systemui/keyguard/domain/interactor/FromDozingTransitionInteractor.kt b/packages/SystemUI/src/com/android/systemui/keyguard/domain/interactor/FromDozingTransitionInteractor.kt index 8ef138eeb16a..61446c19605c 100644 --- a/packages/SystemUI/src/com/android/systemui/keyguard/domain/interactor/FromDozingTransitionInteractor.kt +++ b/packages/SystemUI/src/com/android/systemui/keyguard/domain/interactor/FromDozingTransitionInteractor.kt @@ -302,16 +302,25 @@ constructor( override fun getDefaultAnimatorForTransitionsToState(toState: KeyguardState): ValueAnimator { return ValueAnimator().apply { interpolator = Interpolators.LINEAR - duration = DEFAULT_DURATION.inWholeMilliseconds + duration = + when (toState) { + KeyguardState.GONE -> TO_GONE_DURATION + KeyguardState.GLANCEABLE_HUB -> TO_GLANCEABLE_HUB_DURATION + KeyguardState.LOCKSCREEN -> TO_LOCKSCREEN_DURATION + KeyguardState.OCCLUDED -> TO_OCCLUDED_DURATION + KeyguardState.PRIMARY_BOUNCER -> TO_PRIMARY_BOUNCER_DURATION + else -> DEFAULT_DURATION + }.inWholeMilliseconds } } companion object { const val TAG = "FromDozingTransitionInteractor" private val DEFAULT_DURATION = 500.milliseconds - val TO_LOCKSCREEN_DURATION = DEFAULT_DURATION + val TO_GLANCEABLE_HUB_DURATION = DEFAULT_DURATION val TO_GONE_DURATION = DEFAULT_DURATION + val TO_LOCKSCREEN_DURATION = DEFAULT_DURATION + val TO_OCCLUDED_DURATION = 550.milliseconds val TO_PRIMARY_BOUNCER_DURATION = DEFAULT_DURATION - val TO_GLANCEABLE_HUB_DURATION = DEFAULT_DURATION } } 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 206bbc51f793..51d92f054bbe 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 @@ -393,7 +393,7 @@ constructor( val TO_DOZING_DURATION = 500.milliseconds val TO_DREAMING_DURATION = 933.milliseconds val TO_DREAMING_HOSTED_DURATION = 933.milliseconds - val TO_OCCLUDED_DURATION = 450.milliseconds + val TO_OCCLUDED_DURATION = 550.milliseconds val TO_AOD_DURATION = 500.milliseconds val TO_AOD_FOLD_DURATION = 1100.milliseconds val TO_PRIMARY_BOUNCER_DURATION = DEFAULT_DURATION diff --git a/packages/SystemUI/src/com/android/systemui/keyguard/domain/interactor/FromPrimaryBouncerTransitionInteractor.kt b/packages/SystemUI/src/com/android/systemui/keyguard/domain/interactor/FromPrimaryBouncerTransitionInteractor.kt index e2d7851daf7e..2823b93b4847 100644 --- a/packages/SystemUI/src/com/android/systemui/keyguard/domain/interactor/FromPrimaryBouncerTransitionInteractor.kt +++ b/packages/SystemUI/src/com/android/systemui/keyguard/domain/interactor/FromPrimaryBouncerTransitionInteractor.kt @@ -112,14 +112,18 @@ constructor( keyguardInteractor.isActiveDreamLockscreenHosted, communalSceneInteractor.isIdleOnCommunal ) - .filterRelevantKeyguardState() - .collect { - (isBouncerShowing, isAwake, isActiveDreamLockscreenHosted, isIdleOnCommunal) - -> + .filterRelevantKeyguardStateAnd { (isBouncerShowing, _, _, _) -> + // TODO(b/307976454) - See if we need to listen for SHOW_WHEN_LOCKED + // activities showing up over the bouncer. Camera launch can't show up over + // bouncer since the first power press hides bouncer. Do occluding + // activities auto hide bouncer? Not sure. + !isBouncerShowing + } + .collect { (_, isAwake, isActiveDreamLockscreenHosted, isIdleOnCommunal) -> if ( !maybeStartTransitionToOccludedOrInsecureCamera { state, reason -> startTransitionTo(state, ownerReason = reason) - } && !isBouncerShowing && isAwake && !isActiveDreamLockscreenHosted + } && isAwake && !isActiveDreamLockscreenHosted ) { val toState = if (isIdleOnCommunal) { @@ -241,6 +245,7 @@ constructor( KeyguardState.GONE -> TO_GONE_DURATION KeyguardState.LOCKSCREEN -> TO_LOCKSCREEN_DURATION KeyguardState.GLANCEABLE_HUB -> TO_GLANCEABLE_HUB_DURATION + KeyguardState.OCCLUDED -> TO_OCCLUDED_DURATION else -> DEFAULT_DURATION }.inWholeMilliseconds } @@ -253,7 +258,8 @@ constructor( val TO_GONE_DURATION = 500.milliseconds val TO_GONE_SHORT_DURATION = 200.milliseconds val TO_LOCKSCREEN_DURATION = 450.milliseconds + val TO_OCCLUDED_DURATION = 550.milliseconds val TO_GLANCEABLE_HUB_DURATION = DEFAULT_DURATION - val TO_GONE_SURFACE_BEHIND_VISIBLE_THRESHOLD = 0.5f + val TO_GONE_SURFACE_BEHIND_VISIBLE_THRESHOLD = 0.1f } } 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 046e79cd04c4..42490c4176c6 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 @@ -23,10 +23,7 @@ import android.app.StatusBarManager import android.graphics.Point import android.util.MathUtils import com.android.app.animation.Interpolators -import com.android.app.tracing.FlowTracing.tracedAwaitClose -import com.android.app.tracing.FlowTracing.tracedConflatedCallbackFlow import com.android.systemui.bouncer.data.repository.KeyguardBouncerRepository -import com.android.systemui.common.coroutine.ChannelExt.trySendWithFailureLogging import com.android.systemui.common.shared.model.NotificationContainerBounds import com.android.systemui.common.ui.domain.interactor.ConfigurationInteractor import com.android.systemui.dagger.SysUISingleton @@ -35,9 +32,11 @@ import com.android.systemui.keyguard.MigrateClocksToBlueprint import com.android.systemui.keyguard.data.repository.KeyguardRepository import com.android.systemui.keyguard.shared.model.BiometricUnlockModel import com.android.systemui.keyguard.shared.model.CameraLaunchSourceModel +import com.android.systemui.keyguard.shared.model.CameraLaunchType import com.android.systemui.keyguard.shared.model.DozeStateModel import com.android.systemui.keyguard.shared.model.DozeStateModel.Companion.isDozeOff import com.android.systemui.keyguard.shared.model.DozeTransitionModel +import com.android.systemui.keyguard.shared.model.Edge import com.android.systemui.keyguard.shared.model.KeyguardState.AOD import com.android.systemui.keyguard.shared.model.KeyguardState.GONE import com.android.systemui.keyguard.shared.model.KeyguardState.LOCKSCREEN @@ -48,11 +47,8 @@ import com.android.systemui.scene.domain.interactor.SceneInteractor import com.android.systemui.scene.shared.flag.SceneContainerFlag import com.android.systemui.scene.shared.model.Scenes import com.android.systemui.shade.data.repository.ShadeRepository -import com.android.systemui.statusbar.CommandQueue -import com.android.systemui.statusbar.notification.NotificationUtils.interpolate import com.android.systemui.statusbar.notification.stack.domain.interactor.SharedNotificationContainerInteractor import com.android.systemui.util.kotlin.Utils.Companion.sample as sampleCombine -import com.android.systemui.util.kotlin.pairwise import com.android.systemui.util.kotlin.sample import javax.inject.Inject import javax.inject.Provider @@ -69,9 +65,7 @@ import kotlinx.coroutines.flow.combineTransform import kotlinx.coroutines.flow.debounce import kotlinx.coroutines.flow.distinctUntilChanged import kotlinx.coroutines.flow.filter -import kotlinx.coroutines.flow.first import kotlinx.coroutines.flow.flatMapLatest -import kotlinx.coroutines.flow.flow import kotlinx.coroutines.flow.flowOf import kotlinx.coroutines.flow.map import kotlinx.coroutines.flow.merge @@ -87,7 +81,6 @@ class KeyguardInteractor @Inject constructor( private val repository: KeyguardRepository, - private val commandQueue: CommandQueue, powerInteractor: PowerInteractor, bouncerRepository: KeyguardBouncerRepository, configurationInteractor: ConfigurationInteractor, @@ -102,55 +95,34 @@ constructor( // TODO(b/296118689): move to a repository private val _notificationPlaceholderBounds = MutableStateFlow(NotificationContainerBounds()) - // When going to AOD, we interpolate bounds when receiving the new bounds - // When going back to LS, we'll apply new bounds directly - private val _nonSplitShadeNotifciationPlaceholderBounds = - _notificationPlaceholderBounds.pairwise().flatMapLatest { (oldBounds, newBounds) -> - val lastChangeStep = keyguardTransitionInteractor.transitionState.first() - if (lastChangeStep.to == AOD) { - keyguardTransitionInteractor.transitionState.map { step -> - val startingProgress = lastChangeStep.value - val progress = step.value - if (step.to == AOD && progress >= startingProgress && startingProgress < 1f) { - val adjustedProgress = - ((progress - startingProgress) / (1F - startingProgress)).coerceIn( - 0F, - 1F - ) - val top = interpolate(oldBounds.top, newBounds.top, adjustedProgress) - val bottom = - interpolate( - oldBounds.bottom, - newBounds.bottom, - adjustedProgress.coerceIn(0F, 1F) - ) - NotificationContainerBounds(top = top, bottom = bottom) - } else { - newBounds - } - } - } else { - flow { emit(newBounds) } - } - } - /** Bounds of the notification container. */ val notificationContainerBounds: StateFlow<NotificationContainerBounds> by lazy { SceneContainerFlag.assertInLegacyMode() - combine( + combineTransform( _notificationPlaceholderBounds, - _nonSplitShadeNotifciationPlaceholderBounds, sharedNotificationContainerInteractor.get().configurationBasedDimensions, - ) { bounds, nonSplitShadeBounds: NotificationContainerBounds, cfg -> + keyguardTransitionInteractor.isInTransition( + edge = Edge.create(from = LOCKSCREEN, to = AOD) + ), + ) { bounds, cfg, isTransitioningToAod -> + if (isTransitioningToAod) { + // Keep bounds stable during this transition, to prevent cases like smartspace + // popping in and adjusting the bounds. A prime example would be media playing, + // which then updates smartspace on transition to AOD + return@combineTransform + } + // We offset the placeholder bounds by the configured top margin to account for // legacy placement behavior within notifications for splitshade. - if (MigrateClocksToBlueprint.isEnabled) { - if (cfg.useSplitShade) { - bounds.copy(bottom = bounds.bottom - cfg.keyguardSplitShadeTopMargin) - } else { - nonSplitShadeBounds - } - } else bounds + emit( + if (MigrateClocksToBlueprint.isEnabled) { + if (cfg.useSplitShade) { + bounds.copy(bottom = bounds.bottom - cfg.keyguardSplitShadeTopMargin) + } else { + bounds + } + } else bounds + ) } .stateIn( scope = applicationScope, @@ -198,22 +170,7 @@ constructor( /** Event for when the camera gesture is detected */ val onCameraLaunchDetected: Flow<CameraLaunchSourceModel> = - tracedConflatedCallbackFlow("KeyguardInteractor#onCameraLaunchDetected") { - val callback = - object : CommandQueue.Callbacks { - override fun onCameraLaunchGestureDetected(source: Int) { - trySendWithFailureLogging( - cameraLaunchSourceIntToModel(source), - TAG, - "updated onCameraLaunchGestureDetected" - ) - } - } - - commandQueue.addCallback(callback) - - tracedAwaitClose("onCameraLaunchDetected") { commandQueue.removeCallback(callback) } - } + repository.onCameraLaunchDetected.filter { it.type != CameraLaunchType.IGNORE } /** * Dozing and dreaming have overlapping events. If the doze state remains in FINISH, it means @@ -310,7 +267,7 @@ constructor( when { isKeyguardVisible -> false isPrimaryBouncerShowing -> false - else -> cameraLaunchEvent == CameraLaunchSourceModel.POWER_DOUBLE_TAP + else -> cameraLaunchEvent.type == CameraLaunchType.POWER_DOUBLE_TAP } } .onStart { emit(false) } @@ -440,16 +397,15 @@ constructor( return repository.isKeyguardShowing() } - private fun cameraLaunchSourceIntToModel(value: Int): CameraLaunchSourceModel { + private fun cameraLaunchSourceIntToType(value: Int): CameraLaunchType { return when (value) { - StatusBarManager.CAMERA_LAUNCH_SOURCE_WIGGLE -> CameraLaunchSourceModel.WIGGLE + StatusBarManager.CAMERA_LAUNCH_SOURCE_WIGGLE -> CameraLaunchType.WIGGLE StatusBarManager.CAMERA_LAUNCH_SOURCE_POWER_DOUBLE_TAP -> - CameraLaunchSourceModel.POWER_DOUBLE_TAP - StatusBarManager.CAMERA_LAUNCH_SOURCE_LIFT_TRIGGER -> - CameraLaunchSourceModel.LIFT_TRIGGER + CameraLaunchType.POWER_DOUBLE_TAP + StatusBarManager.CAMERA_LAUNCH_SOURCE_LIFT_TRIGGER -> CameraLaunchType.LIFT_TRIGGER StatusBarManager.CAMERA_LAUNCH_SOURCE_QUICK_AFFORDANCE -> - CameraLaunchSourceModel.QUICK_AFFORDANCE - else -> throw IllegalArgumentException("Invalid CameraLaunchSourceModel value: $value") + CameraLaunchType.QUICK_AFFORDANCE + else -> throw IllegalArgumentException("Invalid CameraLaunchType value: $value") } } @@ -508,6 +464,11 @@ constructor( fromLockscreenTransitionInteractor.get().dismissKeyguard() } + fun onCameraLaunchDetected(source: Int) { + repository.onCameraLaunchDetected.value = + CameraLaunchSourceModel(type = cameraLaunchSourceIntToType(source)) + } + companion object { private const val TAG = "KeyguardInteractor" } diff --git a/packages/SystemUI/src/com/android/systemui/keyguard/domain/interactor/KeyguardTransitionBootInteractor.kt b/packages/SystemUI/src/com/android/systemui/keyguard/domain/interactor/KeyguardTransitionBootInteractor.kt index 805dbb08d1ac..2ebd9e8c5f2b 100644 --- a/packages/SystemUI/src/com/android/systemui/keyguard/domain/interactor/KeyguardTransitionBootInteractor.kt +++ b/packages/SystemUI/src/com/android/systemui/keyguard/domain/interactor/KeyguardTransitionBootInteractor.kt @@ -30,6 +30,7 @@ import com.android.systemui.statusbar.policy.domain.interactor.DeviceProvisionin import javax.inject.Inject import kotlinx.coroutines.CoroutineScope import kotlinx.coroutines.ExperimentalCoroutinesApi +import kotlinx.coroutines.flow.Flow import kotlinx.coroutines.flow.first import kotlinx.coroutines.flow.map import kotlinx.coroutines.launch @@ -52,11 +53,12 @@ constructor( * then we'll seed the repository with a transition from OFF -> GONE. */ @OptIn(ExperimentalCoroutinesApi::class) - private val showLockscreenOnBoot = + private val showLockscreenOnBoot: Flow<Boolean> by lazy { deviceProvisioningInteractor.isDeviceProvisioned.map { provisioned -> (provisioned || deviceEntryInteractor.isAuthenticationRequired()) && deviceEntryInteractor.isLockscreenEnabled() } + } override fun start() { scope.launch { diff --git a/packages/SystemUI/src/com/android/systemui/keyguard/shared/model/CameraLaunchSourceModel.kt b/packages/SystemUI/src/com/android/systemui/keyguard/shared/model/CameraLaunchSourceModel.kt index 19baf7705546..c01765146ed0 100644 --- a/packages/SystemUI/src/com/android/systemui/keyguard/shared/model/CameraLaunchSourceModel.kt +++ b/packages/SystemUI/src/com/android/systemui/keyguard/shared/model/CameraLaunchSourceModel.kt @@ -15,14 +15,8 @@ */ package com.android.systemui.keyguard.shared.model -/** Camera launch sources */ -enum class CameraLaunchSourceModel { - /** Device is wiggled */ - WIGGLE, - /** Power button has been double tapped */ - POWER_DOUBLE_TAP, - /** Device has been lifted */ - LIFT_TRIGGER, - /** Quick affordance button has been pressed */ - QUICK_AFFORDANCE, -} +/** Camera launch source, with type and time detected */ +data class CameraLaunchSourceModel( + val type: CameraLaunchType = CameraLaunchType.IGNORE, + val detectedTime: Long = System.currentTimeMillis(), +) diff --git a/packages/SystemUI/src/com/android/systemui/keyguard/shared/model/CameraLaunchType.kt b/packages/SystemUI/src/com/android/systemui/keyguard/shared/model/CameraLaunchType.kt new file mode 100644 index 000000000000..984abbbdb955 --- /dev/null +++ b/packages/SystemUI/src/com/android/systemui/keyguard/shared/model/CameraLaunchType.kt @@ -0,0 +1,30 @@ +/* + * Copyright (C) 2024 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License + */ +package com.android.systemui.keyguard.shared.model + +/** Camera launch sources */ +enum class CameraLaunchType { + /** Models no value */ + IGNORE, + /** Device is wiggled */ + WIGGLE, + /** Power button has been double tapped */ + POWER_DOUBLE_TAP, + /** Device has been lifted */ + LIFT_TRIGGER, + /** Quick affordance button has been pressed */ + QUICK_AFFORDANCE, +} diff --git a/packages/SystemUI/src/com/android/systemui/keyguard/ui/binder/AlternateBouncerViewBinder.kt b/packages/SystemUI/src/com/android/systemui/keyguard/ui/binder/AlternateBouncerViewBinder.kt index db33acb93dc6..a250b22dde07 100644 --- a/packages/SystemUI/src/com/android/systemui/keyguard/ui/binder/AlternateBouncerViewBinder.kt +++ b/packages/SystemUI/src/com/android/systemui/keyguard/ui/binder/AlternateBouncerViewBinder.kt @@ -37,6 +37,7 @@ import com.android.systemui.deviceentry.shared.DeviceEntryUdfpsRefactor import com.android.systemui.deviceentry.ui.binder.UdfpsAccessibilityOverlayBinder import com.android.systemui.deviceentry.ui.view.UdfpsAccessibilityOverlay import com.android.systemui.deviceentry.ui.viewmodel.AlternateBouncerUdfpsAccessibilityOverlayViewModel +import com.android.systemui.keyguard.DismissCallbackRegistry import com.android.systemui.keyguard.ui.view.DeviceEntryIconView import com.android.systemui.keyguard.ui.viewmodel.AlternateBouncerDependencies import com.android.systemui.keyguard.ui.viewmodel.AlternateBouncerUdfpsIconViewModel @@ -66,6 +67,7 @@ constructor( private val alternateBouncerDependencies: Lazy<AlternateBouncerDependencies>, private val windowManager: Lazy<WindowManager>, private val layoutInflater: Lazy<LayoutInflater>, + private val dismissCallbackRegistry: DismissCallbackRegistry, ) : CoreStartable { private val layoutParams: WindowManager.LayoutParams get() = @@ -162,6 +164,7 @@ constructor( fun onBackRequested() { alternateBouncerDependencies.get().viewModel.hideAlternateBouncer() + dismissCallbackRegistry.notifyDismissCancelled() } } diff --git a/packages/SystemUI/src/com/android/systemui/keyguard/ui/binder/DeviceEntryIconViewBinder.kt b/packages/SystemUI/src/com/android/systemui/keyguard/ui/binder/DeviceEntryIconViewBinder.kt index 1b9788f2d401..4d6577c0423a 100644 --- a/packages/SystemUI/src/com/android/systemui/keyguard/ui/binder/DeviceEntryIconViewBinder.kt +++ b/packages/SystemUI/src/com/android/systemui/keyguard/ui/binder/DeviceEntryIconViewBinder.kt @@ -74,15 +74,26 @@ object DeviceEntryIconViewBinder { val bgView = view.bgView longPressHandlingView.listener = object : LongPressHandlingView.Listener { - override fun onLongPressDetected(view: View, x: Int, y: Int, isA11yAction: Boolean) { - if (!isA11yAction && falsingManager.isFalseLongTap(FalsingManager.LOW_PENALTY)) { + override fun onLongPressDetected( + view: View, + x: Int, + y: Int, + isA11yAction: Boolean + ) { + if ( + !isA11yAction && falsingManager.isFalseLongTap(FalsingManager.LOW_PENALTY) + ) { return } vibratorHelper.performHapticFeedback( view, HapticFeedbackConstants.CONFIRM, ) - applicationScope.launch { viewModel.onUserInteraction() } + applicationScope.launch { + view.clearFocus() + view.clearAccessibilityFocus() + viewModel.onUserInteraction() + } } } @@ -95,6 +106,7 @@ object DeviceEntryIconViewBinder { launch("$TAG#viewModel.isVisible") { viewModel.isVisible.collect { isVisible -> longPressHandlingView.isInvisible = !isVisible + view.isClickable = isVisible } } launch("$TAG#viewModel.isLongPressEnabled") { @@ -131,7 +143,11 @@ object DeviceEntryIconViewBinder { view, HapticFeedbackConstants.CONFIRM, ) - applicationScope.launch { viewModel.onUserInteraction() } + applicationScope.launch { + view.clearFocus() + view.clearAccessibilityFocus() + viewModel.onUserInteraction() + } } } else { view.setOnClickListener(null) diff --git a/packages/SystemUI/src/com/android/systemui/keyguard/ui/transitions/DeviceEntryIconTransitionModule.kt b/packages/SystemUI/src/com/android/systemui/keyguard/ui/transitions/DeviceEntryIconTransitionModule.kt index dc7a649c8e6c..0032c2f036d3 100644 --- a/packages/SystemUI/src/com/android/systemui/keyguard/ui/transitions/DeviceEntryIconTransitionModule.kt +++ b/packages/SystemUI/src/com/android/systemui/keyguard/ui/transitions/DeviceEntryIconTransitionModule.kt @@ -18,6 +18,7 @@ package com.android.systemui.keyguard.ui.transitions import com.android.systemui.keyguard.ui.viewmodel.AlternateBouncerToAodTransitionViewModel import com.android.systemui.keyguard.ui.viewmodel.AlternateBouncerToDozingTransitionViewModel import com.android.systemui.keyguard.ui.viewmodel.AlternateBouncerToGoneTransitionViewModel +import com.android.systemui.keyguard.ui.viewmodel.AlternateBouncerToLockscreenTransitionViewModel import com.android.systemui.keyguard.ui.viewmodel.AlternateBouncerToOccludedTransitionViewModel import com.android.systemui.keyguard.ui.viewmodel.AlternateBouncerToPrimaryBouncerTransitionViewModel import com.android.systemui.keyguard.ui.viewmodel.AodToGoneTransitionViewModel @@ -80,6 +81,12 @@ abstract class DeviceEntryIconTransitionModule { @Binds @IntoSet + abstract fun alternateBouncerToLockscreen( + impl: AlternateBouncerToLockscreenTransitionViewModel + ): DeviceEntryIconTransition + + @Binds + @IntoSet abstract fun alternateBouncerToOccluded( impl: AlternateBouncerToOccludedTransitionViewModel ): DeviceEntryIconTransition diff --git a/packages/SystemUI/src/com/android/systemui/keyguard/ui/viewmodel/AlternateBouncerToLockscreenTransitionViewModel.kt b/packages/SystemUI/src/com/android/systemui/keyguard/ui/viewmodel/AlternateBouncerToLockscreenTransitionViewModel.kt new file mode 100644 index 000000000000..b04521cec881 --- /dev/null +++ b/packages/SystemUI/src/com/android/systemui/keyguard/ui/viewmodel/AlternateBouncerToLockscreenTransitionViewModel.kt @@ -0,0 +1,62 @@ +/* + * Copyright (C) 2024 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.android.systemui.keyguard.ui.viewmodel + +import android.util.MathUtils +import com.android.systemui.dagger.SysUISingleton +import com.android.systemui.keyguard.domain.interactor.FromAlternateBouncerTransitionInteractor +import com.android.systemui.keyguard.shared.model.Edge +import com.android.systemui.keyguard.shared.model.KeyguardState.ALTERNATE_BOUNCER +import com.android.systemui.keyguard.shared.model.KeyguardState.LOCKSCREEN +import com.android.systemui.keyguard.ui.KeyguardTransitionAnimationFlow +import com.android.systemui.keyguard.ui.transitions.DeviceEntryIconTransition +import javax.inject.Inject +import kotlin.time.Duration.Companion.milliseconds +import kotlinx.coroutines.ExperimentalCoroutinesApi +import kotlinx.coroutines.flow.Flow + +/** + * Breaks down ALTERNATE_BOUNCER->LOCKSCREEN transition into discrete steps for corresponding views + * to consume. + */ +@ExperimentalCoroutinesApi +@SysUISingleton +class AlternateBouncerToLockscreenTransitionViewModel +@Inject +constructor( + animationFlow: KeyguardTransitionAnimationFlow, +) : DeviceEntryIconTransition { + private val transitionAnimation = + animationFlow.setup( + duration = FromAlternateBouncerTransitionInteractor.TO_LOCKSCREEN_DURATION, + edge = Edge.create(from = ALTERNATE_BOUNCER, to = LOCKSCREEN), + ) + + fun lockscreenAlpha(viewState: ViewStateAccessor): Flow<Float> { + var startAlpha = 1f + return transitionAnimation.sharedFlow( + duration = 250.milliseconds, + onStart = { startAlpha = viewState.alpha() }, + onStep = { MathUtils.lerp(startAlpha, 1f, it) }, + ) + } + + val deviceEntryBackgroundViewAlpha: Flow<Float> = + transitionAnimation.immediatelyTransitionTo(1f) + override val deviceEntryParentViewAlpha: Flow<Float> = + transitionAnimation.immediatelyTransitionTo(1f) +} diff --git a/packages/SystemUI/src/com/android/systemui/keyguard/ui/viewmodel/KeyguardRootViewModel.kt b/packages/SystemUI/src/com/android/systemui/keyguard/ui/viewmodel/KeyguardRootViewModel.kt index 350ceb47848f..11889c568275 100644 --- a/packages/SystemUI/src/com/android/systemui/keyguard/ui/viewmodel/KeyguardRootViewModel.kt +++ b/packages/SystemUI/src/com/android/systemui/keyguard/ui/viewmodel/KeyguardRootViewModel.kt @@ -85,6 +85,8 @@ constructor( private val notificationsKeyguardInteractor: NotificationsKeyguardInteractor, private val alternateBouncerToGoneTransitionViewModel: AlternateBouncerToGoneTransitionViewModel, + private val alternateBouncerToLockscreenTransitionViewModel: + AlternateBouncerToLockscreenTransitionViewModel, private val aodToGoneTransitionViewModel: AodToGoneTransitionViewModel, private val aodToLockscreenTransitionViewModel: AodToLockscreenTransitionViewModel, private val aodToOccludedTransitionViewModel: AodToOccludedTransitionViewModel, @@ -238,6 +240,7 @@ constructor( alphaOnShadeExpansion, keyguardInteractor.dismissAlpha, alternateBouncerToGoneTransitionViewModel.lockscreenAlpha(viewState), + alternateBouncerToLockscreenTransitionViewModel.lockscreenAlpha(viewState), aodToGoneTransitionViewModel.lockscreenAlpha(viewState), aodToLockscreenTransitionViewModel.lockscreenAlpha(viewState), aodToOccludedTransitionViewModel.lockscreenAlpha(viewState), diff --git a/packages/SystemUI/src/com/android/systemui/keyguard/ui/viewmodel/LockscreenContentViewModel.kt b/packages/SystemUI/src/com/android/systemui/keyguard/ui/viewmodel/LockscreenContentViewModel.kt index 4bfefda63466..3fffeffec254 100644 --- a/packages/SystemUI/src/com/android/systemui/keyguard/ui/viewmodel/LockscreenContentViewModel.kt +++ b/packages/SystemUI/src/com/android/systemui/keyguard/ui/viewmodel/LockscreenContentViewModel.kt @@ -17,7 +17,7 @@ package com.android.systemui.keyguard.ui.viewmodel import android.content.res.Resources -import com.android.compose.animation.scene.SceneKey +import com.android.compose.animation.scene.ContentKey import com.android.internal.annotations.VisibleForTesting import com.android.systemui.biometrics.AuthController import com.android.systemui.dagger.SysUISingleton @@ -90,12 +90,12 @@ constructor( /** * Returns a flow that indicates whether lockscreen notifications should be rendered in the - * given [sceneKey]. + * given [contentKey]. */ - fun areNotificationsVisible(sceneKey: SceneKey): Flow<Boolean> { + fun areNotificationsVisible(contentKey: ContentKey): Flow<Boolean> { // `Scenes.NotificationsShade` renders its own separate notifications stack, so when it's // open we avoid rendering the lockscreen notifications stack. - if (sceneKey == Scenes.NotificationsShade) { + if (contentKey == Scenes.NotificationsShade) { return flowOf(false) } diff --git a/packages/SystemUI/src/com/android/systemui/lifecycle/RepeatWhenAttached.kt b/packages/SystemUI/src/com/android/systemui/lifecycle/RepeatWhenAttached.kt index bf80e1870f1b..661da6d2af13 100644 --- a/packages/SystemUI/src/com/android/systemui/lifecycle/RepeatWhenAttached.kt +++ b/packages/SystemUI/src/com/android/systemui/lifecycle/RepeatWhenAttached.kt @@ -30,10 +30,21 @@ import com.android.app.tracing.coroutines.launch import com.android.systemui.Flags.coroutineTracing import com.android.systemui.util.Assert import com.android.systemui.util.Compile +import com.android.systemui.utils.coroutines.flow.conflatedCallbackFlow +import com.android.systemui.utils.coroutines.flow.flatMapLatestConflated import kotlin.coroutines.CoroutineContext import kotlin.coroutines.EmptyCoroutineContext +import kotlinx.coroutines.CoroutineScope import kotlinx.coroutines.Dispatchers import kotlinx.coroutines.DisposableHandle +import kotlinx.coroutines.awaitCancellation +import kotlinx.coroutines.channels.awaitClose +import kotlinx.coroutines.coroutineScope +import kotlinx.coroutines.flow.Flow +import kotlinx.coroutines.flow.collectLatest +import kotlinx.coroutines.flow.emptyFlow +import kotlinx.coroutines.flow.map +import kotlinx.coroutines.flow.onStart /** * Runs the given [block] every time the [View] becomes attached (or immediately after calling this @@ -216,6 +227,102 @@ private fun inferTraceSectionName(): String { } /** + * Runs the given [block] every time the [View] becomes attached (or immediately after calling this + * function, if the view was already attached), automatically canceling the work when the view + * becomes detached. + * + * Only use from the main thread. + * + * The [block] may be run multiple times, running once per every time the view is attached. + */ +@MainThread +suspend fun View.repeatWhenAttachedToWindow(block: suspend CoroutineScope.() -> Unit): Nothing { + Assert.isMainThread() + isAttached.collectLatest { if (it) coroutineScope { block() } } + awaitCancellation() // satisfies return type of Nothing +} + +/** + * Runs the given [block] every time the [Window] this [View] is attached to becomes visible (or + * immediately after calling this function, if the window is already visible), automatically + * canceling the work when the window becomes invisible. + * + * Only use from the main thread. + * + * The [block] may be run multiple times, running once per every time the window becomes visible. + */ +@MainThread +suspend fun View.repeatWhenWindowIsVisible(block: suspend CoroutineScope.() -> Unit): Nothing { + Assert.isMainThread() + isWindowVisible.collectLatest { if (it) coroutineScope { block() } } + awaitCancellation() // satisfies return type of Nothing +} + +/** + * Runs the given [block] every time the [Window] this [View] is attached to has focus (or + * immediately after calling this function, if the window is already focused), automatically + * canceling the work when the window loses focus. + * + * Only use from the main thread. + * + * The [block] may be run multiple times, running once per every time the window is focused. + */ +@MainThread +suspend fun View.repeatWhenWindowHasFocus(block: suspend CoroutineScope.() -> Unit): Nothing { + Assert.isMainThread() + isWindowFocused.collectLatest { if (it) coroutineScope { block() } } + awaitCancellation() // satisfies return type of Nothing +} + +private val View.isAttached + get() = conflatedCallbackFlow { + val onAttachListener = + object : View.OnAttachStateChangeListener { + override fun onViewAttachedToWindow(v: View) { + Assert.isMainThread() + trySend(true) + } + + override fun onViewDetachedFromWindow(v: View) { + trySend(false) + } + } + addOnAttachStateChangeListener(onAttachListener) + trySend(isAttachedToWindow) + awaitClose { removeOnAttachStateChangeListener(onAttachListener) } + } + +private val View.currentViewTreeObserver: Flow<ViewTreeObserver?> + get() = isAttached.map { if (it) viewTreeObserver else null } + +private val View.isWindowVisible + get() = + currentViewTreeObserver.flatMapLatestConflated { vto -> + vto?.isWindowVisible?.onStart { emit(windowVisibility == View.VISIBLE) } ?: emptyFlow() + } + +private val View.isWindowFocused + get() = + currentViewTreeObserver.flatMapLatestConflated { vto -> + vto?.isWindowFocused?.onStart { emit(hasWindowFocus()) } ?: emptyFlow() + } + +private val ViewTreeObserver.isWindowFocused + get() = conflatedCallbackFlow { + val listener = ViewTreeObserver.OnWindowFocusChangeListener { trySend(it) } + addOnWindowFocusChangeListener(listener) + awaitClose { removeOnWindowFocusChangeListener(listener) } + } + +private val ViewTreeObserver.isWindowVisible + get() = conflatedCallbackFlow { + val listener = + ViewTreeObserver.OnWindowVisibilityChangeListener { v -> trySend(v == View.VISIBLE) } + addOnWindowVisibilityChangeListener(listener) + awaitClose { removeOnWindowVisibilityChangeListener(listener) } + } + +/** * Even though there is only has one usage of `Dispatchers.Main` in this file, we cache it in a * top-level property so that we do not unnecessarily create new `CoroutineContext` objects for * tracing on each call to [repeatWhenAttached]. It is okay to reuse a single instance of the diff --git a/packages/SystemUI/src/com/android/systemui/navigationbar/gestural/EdgeBackGestureHandler.java b/packages/SystemUI/src/com/android/systemui/navigationbar/gestural/EdgeBackGestureHandler.java index 947336d41590..9eca34f88a78 100644 --- a/packages/SystemUI/src/com/android/systemui/navigationbar/gestural/EdgeBackGestureHandler.java +++ b/packages/SystemUI/src/com/android/systemui/navigationbar/gestural/EdgeBackGestureHandler.java @@ -76,6 +76,7 @@ import com.android.internal.policy.GestureNavigationSettingsObserver; import com.android.systemui.dagger.qualifiers.Background; import com.android.systemui.model.SysUiState; import com.android.systemui.navigationbar.NavigationModeController; +import com.android.systemui.navigationbar.gestural.domain.GestureInteractor; import com.android.systemui.plugins.FalsingManager; import com.android.systemui.plugins.NavigationEdgeBackPlugin; import com.android.systemui.plugins.PluginListener; @@ -95,15 +96,14 @@ import com.android.systemui.statusbar.NotificationShadeWindowController; import com.android.systemui.statusbar.phone.LightBarController; import com.android.systemui.util.concurrency.BackPanelUiThread; import com.android.systemui.util.concurrency.UiThreadContext; +import com.android.systemui.util.kotlin.JavaAdapter; import com.android.wm.shell.back.BackAnimation; import com.android.wm.shell.desktopmode.DesktopMode; import com.android.wm.shell.pip.Pip; import java.io.PrintWriter; import java.util.ArrayDeque; -import java.util.ArrayList; import java.util.Date; -import java.util.List; import java.util.Locale; import java.util.Map; import java.util.Optional; @@ -157,12 +157,7 @@ public class EdgeBackGestureHandler implements PluginListener<NavigationEdgeBack private TaskStackChangeListener mTaskStackListener = new TaskStackChangeListener() { @Override public void onTaskStackChanged() { - if (edgebackGestureHandlerGetRunningTasksBackground()) { - mBackgroundExecutor.execute(() -> mGestureBlockingActivityRunning.set( - isGestureBlockingActivityRunning())); - } else { - mGestureBlockingActivityRunning.set(isGestureBlockingActivityRunning()); - } + updateRunningActivityGesturesBlocked(); } @Override public void onTaskCreated(int taskId, ComponentName componentName) { @@ -209,8 +204,6 @@ public class EdgeBackGestureHandler implements PluginListener<NavigationEdgeBack private final Optional<DesktopMode> mDesktopModeOptional; private final FalsingManager mFalsingManager; private final Configuration mLastReportedConfig = new Configuration(); - // Activities which should not trigger Back gesture. - private final List<ComponentName> mGestureBlockingActivities = new ArrayList<>(); private final Point mDisplaySize = new Point(); private final int mDisplayId; @@ -227,6 +220,10 @@ public class EdgeBackGestureHandler implements PluginListener<NavigationEdgeBack mBackGestureTfClassifierProviderProvider; private final Provider<LightBarController> mLightBarControllerProvider; + private final GestureInteractor mGestureInteractor; + + private final JavaAdapter mJavaAdapter; + // The left side edge width where touch down is allowed private int mEdgeWidthLeft; // The right side edge width where touch down is allowed @@ -426,7 +423,9 @@ public class EdgeBackGestureHandler implements PluginListener<NavigationEdgeBack FalsingManager falsingManager, Provider<BackGestureTfClassifierProvider> backGestureTfClassifierProviderProvider, Provider<LightBarController> lightBarControllerProvider, - NotificationShadeWindowController notificationShadeWindowController) { + NotificationShadeWindowController notificationShadeWindowController, + GestureInteractor gestureInteractor, + JavaAdapter javaAdapter) { mContext = context; mDisplayId = context.getDisplayId(); mUiThreadContext = uiThreadContext; @@ -446,7 +445,13 @@ public class EdgeBackGestureHandler implements PluginListener<NavigationEdgeBack mFalsingManager = falsingManager; mBackGestureTfClassifierProviderProvider = backGestureTfClassifierProviderProvider; mLightBarControllerProvider = lightBarControllerProvider; + mGestureInteractor = gestureInteractor; + mJavaAdapter = javaAdapter; mLastReportedConfig.setTo(mContext.getResources().getConfiguration()); + + mJavaAdapter.alwaysCollectFlow(mGestureInteractor.getGestureBlockedActivities(), + componentNames -> updateRunningActivityGesturesBlocked()); + ComponentName recentsComponentName = ComponentName.unflattenFromString( context.getString(com.android.internal.R.string.config_recentsComponentName)); if (recentsComponentName != null) { @@ -466,8 +471,9 @@ public class EdgeBackGestureHandler implements PluginListener<NavigationEdgeBack } else { String[] gestureBlockingActivities = resources.getStringArray(resId); for (String gestureBlockingActivity : gestureBlockingActivities) { - mGestureBlockingActivities.add( - ComponentName.unflattenFromString(gestureBlockingActivity)); + mGestureInteractor.addGestureBlockedActivity( + ComponentName.unflattenFromString(gestureBlockingActivity), + GestureInteractor.Scope.Local); } } } catch (NameNotFoundException e) { @@ -561,6 +567,15 @@ public class EdgeBackGestureHandler implements PluginListener<NavigationEdgeBack } } + private void updateRunningActivityGesturesBlocked() { + if (edgebackGestureHandlerGetRunningTasksBackground()) { + mBackgroundExecutor.execute(() -> mGestureBlockingActivityRunning.set( + isGestureBlockingActivityRunning())); + } else { + mGestureBlockingActivityRunning.set(isGestureBlockingActivityRunning()); + } + } + /** * Called when the nav/task bar is attached. */ @@ -1293,7 +1308,8 @@ public class EdgeBackGestureHandler implements PluginListener<NavigationEdgeBack } else { mPackageName = "_UNKNOWN"; } - return topActivity != null && mGestureBlockingActivities.contains(topActivity); + + return topActivity != null && mGestureInteractor.areGesturesBlocked(topActivity); } public void setBackAnimation(BackAnimation backAnimation) { @@ -1342,6 +1358,10 @@ public class EdgeBackGestureHandler implements PluginListener<NavigationEdgeBack private final Provider<LightBarController> mLightBarControllerProvider; private final NotificationShadeWindowController mNotificationShadeWindowController; + private final GestureInteractor mGestureInteractor; + + private final JavaAdapter mJavaAdapter; + @Inject public Factory(OverviewProxyService overviewProxyService, SysUiState sysUiState, @@ -1361,8 +1381,10 @@ public class EdgeBackGestureHandler implements PluginListener<NavigationEdgeBack FalsingManager falsingManager, Provider<BackGestureTfClassifierProvider> backGestureTfClassifierProviderProvider, - Provider<LightBarController> lightBarControllerProvider, - NotificationShadeWindowController notificationShadeWindowController) { + Provider<LightBarController> lightBarControllerProvider, + NotificationShadeWindowController notificationShadeWindowController, + GestureInteractor gestureInteractor, + JavaAdapter javaAdapter) { mOverviewProxyService = overviewProxyService; mSysUiState = sysUiState; mPluginManager = pluginManager; @@ -1382,6 +1404,8 @@ public class EdgeBackGestureHandler implements PluginListener<NavigationEdgeBack mBackGestureTfClassifierProviderProvider = backGestureTfClassifierProviderProvider; mLightBarControllerProvider = lightBarControllerProvider; mNotificationShadeWindowController = notificationShadeWindowController; + mGestureInteractor = gestureInteractor; + mJavaAdapter = javaAdapter; } /** Construct a {@link EdgeBackGestureHandler}. */ @@ -1407,7 +1431,9 @@ public class EdgeBackGestureHandler implements PluginListener<NavigationEdgeBack mFalsingManager, mBackGestureTfClassifierProviderProvider, mLightBarControllerProvider, - mNotificationShadeWindowController)); + mNotificationShadeWindowController, + mGestureInteractor, + mJavaAdapter)); } } diff --git a/packages/SystemUI/src/com/android/systemui/navigationbar/gestural/dagger/GestureModule.kt b/packages/SystemUI/src/com/android/systemui/navigationbar/gestural/dagger/GestureModule.kt new file mode 100644 index 000000000000..72a84f54ab9f --- /dev/null +++ b/packages/SystemUI/src/com/android/systemui/navigationbar/gestural/dagger/GestureModule.kt @@ -0,0 +1,29 @@ +/* + * Copyright (C) 2024 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.android.systemui.navigationbar.gestural.dagger + +import com.android.systemui.navigationbar.gestural.data.respository.GestureRepository +import com.android.systemui.navigationbar.gestural.data.respository.GestureRepositoryImpl +import dagger.Binds +import dagger.Module + +/** {@link Module} for gesture related dependencies */ +@Module +interface GestureModule { + /** */ + @Binds fun gestureRespoitory(impl: GestureRepositoryImpl): GestureRepository +} diff --git a/packages/SystemUI/src/com/android/systemui/navigationbar/gestural/data/respository/GestureRepository.kt b/packages/SystemUI/src/com/android/systemui/navigationbar/gestural/data/respository/GestureRepository.kt new file mode 100644 index 000000000000..8f35343626e8 --- /dev/null +++ b/packages/SystemUI/src/com/android/systemui/navigationbar/gestural/data/respository/GestureRepository.kt @@ -0,0 +1,63 @@ +/* + * Copyright (C) 2024 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.android.systemui.navigationbar.gestural.data.respository + +import android.content.ComponentName +import android.util.ArraySet +import com.android.systemui.dagger.SysUISingleton +import com.android.systemui.dagger.qualifiers.Main +import javax.inject.Inject +import kotlinx.coroutines.CoroutineDispatcher +import kotlinx.coroutines.flow.MutableStateFlow +import kotlinx.coroutines.flow.StateFlow +import kotlinx.coroutines.withContext + +/** A repository for storing gesture related information */ +interface GestureRepository { + /** A {@link StateFlow} tracking activities currently blocked from gestures. */ + val gestureBlockedActivities: StateFlow<Set<ComponentName>> + + /** Adds an activity to be blocked from gestures. */ + suspend fun addGestureBlockedActivity(activity: ComponentName) + + /** Removes an activity from being blocked from gestures. */ + suspend fun removeGestureBlockedActivity(activity: ComponentName) +} + +@SysUISingleton +class GestureRepositoryImpl +@Inject +constructor(@Main private val mainDispatcher: CoroutineDispatcher) : GestureRepository { + private val _gestureBlockedActivities = MutableStateFlow<Set<ComponentName>>(ArraySet()) + + override val gestureBlockedActivities: StateFlow<Set<ComponentName>> + get() = _gestureBlockedActivities + + override suspend fun addGestureBlockedActivity(activity: ComponentName) = + withContext(mainDispatcher) { + _gestureBlockedActivities.emit( + _gestureBlockedActivities.value.toMutableSet().apply { add(activity) } + ) + } + + override suspend fun removeGestureBlockedActivity(activity: ComponentName) = + withContext(mainDispatcher) { + _gestureBlockedActivities.emit( + _gestureBlockedActivities.value.toMutableSet().apply { remove(activity) } + ) + } +} diff --git a/packages/SystemUI/src/com/android/systemui/navigationbar/gestural/domain/GestureInteractor.kt b/packages/SystemUI/src/com/android/systemui/navigationbar/gestural/domain/GestureInteractor.kt new file mode 100644 index 000000000000..6dc5939b7c1a --- /dev/null +++ b/packages/SystemUI/src/com/android/systemui/navigationbar/gestural/domain/GestureInteractor.kt @@ -0,0 +1,103 @@ +/* + * Copyright (C) 2024 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.android.systemui.navigationbar.gestural.domain + +import android.content.ComponentName +import com.android.systemui.dagger.qualifiers.Application +import com.android.systemui.navigationbar.gestural.data.respository.GestureRepository +import javax.inject.Inject +import kotlinx.coroutines.CoroutineScope +import kotlinx.coroutines.flow.MutableStateFlow +import kotlinx.coroutines.flow.SharingStarted +import kotlinx.coroutines.flow.StateFlow +import kotlinx.coroutines.flow.asStateFlow +import kotlinx.coroutines.flow.combine +import kotlinx.coroutines.flow.stateIn +import kotlinx.coroutines.launch + +/** + * {@link GestureInteractor} helps interact with gesture-related logic, including accessing the + * underlying {@link GestureRepository}. + */ +class GestureInteractor +@Inject +constructor( + private val gestureRepository: GestureRepository, + @Application private val scope: CoroutineScope +) { + enum class Scope { + Local, + Global + } + + private val _localGestureBlockedActivities = MutableStateFlow<Set<ComponentName>>(setOf()) + /** A {@link StateFlow} for listening to changes in Activities where gestures are blocked */ + val gestureBlockedActivities: StateFlow<Set<ComponentName>> + get() = + combine( + gestureRepository.gestureBlockedActivities, + _localGestureBlockedActivities.asStateFlow() + ) { global, local -> + global + local + } + .stateIn(scope, SharingStarted.WhileSubscribed(), setOf()) + + /** + * Adds an {@link Activity} to be blocked based on component when the topmost, focused {@link + * Activity}. + */ + fun addGestureBlockedActivity(activity: ComponentName, gestureScope: Scope) { + scope.launch { + when (gestureScope) { + Scope.Local -> { + _localGestureBlockedActivities.emit( + _localGestureBlockedActivities.value.toMutableSet().apply { add(activity) } + ) + } + Scope.Global -> { + gestureRepository.addGestureBlockedActivity(activity) + } + } + } + } + + /** Removes an {@link Activity} from being blocked from gestures. */ + fun removeGestureBlockedActivity(activity: ComponentName, gestureScope: Scope) { + scope.launch { + when (gestureScope) { + Scope.Local -> { + _localGestureBlockedActivities.emit( + _localGestureBlockedActivities.value.toMutableSet().apply { + remove(activity) + } + ) + } + Scope.Global -> { + gestureRepository.removeGestureBlockedActivity(activity) + } + } + } + } + + /** + * Checks whether the specified {@link Activity} {@link ComponentName} is being blocked from + * gestures. + */ + fun areGesturesBlocked(activity: ComponentName): Boolean { + return gestureBlockedActivities.value.contains(activity) + } +} diff --git a/packages/SystemUI/src/com/android/systemui/power/domain/interactor/PowerInteractor.kt b/packages/SystemUI/src/com/android/systemui/power/domain/interactor/PowerInteractor.kt index 9380d44dc27f..8d48c1d1d23f 100644 --- a/packages/SystemUI/src/com/android/systemui/power/domain/interactor/PowerInteractor.kt +++ b/packages/SystemUI/src/com/android/systemui/power/domain/interactor/PowerInteractor.kt @@ -18,6 +18,7 @@ package com.android.systemui.power.domain.interactor import android.os.PowerManager +import com.android.systemui.camera.CameraGestureHelper import com.android.systemui.classifier.FalsingCollector import com.android.systemui.classifier.FalsingCollectorActual import com.android.systemui.dagger.SysUISingleton @@ -28,6 +29,7 @@ import com.android.systemui.power.shared.model.WakeSleepReason import com.android.systemui.power.shared.model.WakefulnessState import com.android.systemui.statusbar.phone.ScreenOffAnimationController import javax.inject.Inject +import javax.inject.Provider import kotlinx.coroutines.flow.Flow import kotlinx.coroutines.flow.distinctUntilChanged import kotlinx.coroutines.flow.map @@ -41,6 +43,7 @@ constructor( @FalsingCollectorActual private val falsingCollector: FalsingCollector, private val screenOffAnimationController: ScreenOffAnimationController, private val statusBarStateController: StatusBarStateController, + private val cameraGestureHelper: Provider<CameraGestureHelper>, ) { /** Whether the screen is on or off. */ val isInteractive: Flow<Boolean> = repository.isInteractive @@ -206,7 +209,13 @@ constructor( } fun onCameraLaunchGestureDetected() { - repository.updateWakefulness(powerButtonLaunchGestureTriggered = true) + if ( + cameraGestureHelper + .get() + .canCameraGestureBeLaunched(statusBarStateController.getState()) + ) { + repository.updateWakefulness(powerButtonLaunchGestureTriggered = true) + } } companion object { diff --git a/packages/SystemUI/src/com/android/systemui/power/shared/model/WakefulnessModel.kt b/packages/SystemUI/src/com/android/systemui/power/shared/model/WakefulnessModel.kt index 5432793d8117..0f49c94c3195 100644 --- a/packages/SystemUI/src/com/android/systemui/power/shared/model/WakefulnessModel.kt +++ b/packages/SystemUI/src/com/android/systemui/power/shared/model/WakefulnessModel.kt @@ -19,7 +19,7 @@ data class WakefulnessModel( * all use cases. If you need more granular information about a waking/sleeping transition, use * the [KeyguardTransitionInteractor]. */ - internal val internalWakefulnessState: WakefulnessState = WakefulnessState.AWAKE, + val internalWakefulnessState: WakefulnessState = WakefulnessState.AWAKE, val lastWakeReason: WakeSleepReason = WakeSleepReason.OTHER, val lastSleepReason: WakeSleepReason = WakeSleepReason.OTHER, diff --git a/packages/SystemUI/src/com/android/systemui/qs/pipeline/domain/interactor/CurrentTilesInteractor.kt b/packages/SystemUI/src/com/android/systemui/qs/pipeline/domain/interactor/CurrentTilesInteractor.kt index 97b5e87d7167..02379e6efecc 100644 --- a/packages/SystemUI/src/com/android/systemui/qs/pipeline/domain/interactor/CurrentTilesInteractor.kt +++ b/packages/SystemUI/src/com/android/systemui/qs/pipeline/domain/interactor/CurrentTilesInteractor.kt @@ -46,7 +46,7 @@ import com.android.systemui.qs.toProto import com.android.systemui.retail.data.repository.RetailModeRepository import com.android.systemui.settings.UserTracker import com.android.systemui.user.data.repository.UserRepository -import com.android.systemui.util.kotlin.pairwise +import com.android.systemui.util.kotlin.pairwiseBy import dagger.Lazy import java.io.PrintWriter import javax.inject.Inject @@ -63,7 +63,6 @@ import kotlinx.coroutines.flow.filter import kotlinx.coroutines.flow.first import kotlinx.coroutines.flow.flatMapLatest import kotlinx.coroutines.flow.flowOn -import kotlinx.coroutines.flow.map import kotlinx.coroutines.launch import kotlinx.coroutines.withContext @@ -169,17 +168,19 @@ constructor( private val userAndTiles = currentUser .flatMapLatest { userId -> - tileSpecRepository.tilesSpecs(userId).map { UserAndTiles(userId, it) } + val currentTiles = tileSpecRepository.tilesSpecs(userId) + val installedComponents = + installedTilesComponentRepository.getInstalledTilesComponents(userId) + currentTiles.combine(installedComponents) { tiles, components -> + UserTilesAndComponents(userId, tiles, components) + } } .distinctUntilChanged() - .pairwise(UserAndTiles(-1, emptyList())) + .pairwiseBy(UserTilesAndComponents(-1, emptyList(), emptySet())) { prev, new -> + DataWithUserChange(data = new, userChange = prev.userId != new.userId) + } .flowOn(backgroundDispatcher) - private val installedPackagesWithTiles = - currentUser.flatMapLatest { - installedTilesComponentRepository.getInstalledTilesComponents(it) - } - private val minTiles: Int get() = if (retailModeRepository.inRetailMode) { @@ -194,7 +195,6 @@ constructor( } } - @OptIn(ExperimentalCoroutinesApi::class) private fun startTileCollection() { scope.launch { launch { @@ -205,95 +205,82 @@ constructor( } launch(backgroundDispatcher) { - userAndTiles - .combine(installedPackagesWithTiles) { usersAndTiles, packages -> - Data( - usersAndTiles.previousValue, - usersAndTiles.newValue, - packages, - ) - } - .collectLatest { - val newTileList = it.newData.tiles - val userChanged = it.oldData.userId != it.newData.userId - val newUser = it.newData.userId - val components = it.installedComponents - - // Destroy all tiles that are not in the new set - specsToTiles - .filter { - it.key !in newTileList && it.value is TileOrNotInstalled.Tile - } - .forEach { entry -> - logger.logTileDestroyed( - entry.key, - if (userChanged) { - QSPipelineLogger.TileDestroyedReason - .TILE_NOT_PRESENT_IN_NEW_USER - } else { - QSPipelineLogger.TileDestroyedReason.TILE_REMOVED - } - ) - (entry.value as TileOrNotInstalled.Tile).tile.destroy() - } - // MutableMap will keep the insertion order - val newTileMap = mutableMapOf<TileSpec, TileOrNotInstalled>() - - newTileList.forEach { tileSpec -> - if (tileSpec !in newTileMap) { - if ( - tileSpec is TileSpec.CustomTileSpec && - tileSpec.componentName !in components - ) { - newTileMap[tileSpec] = TileOrNotInstalled.NotInstalled + userAndTiles.collectLatest { + val newUser = it.userId + val newTileList = it.tiles + val components = it.installedComponents + val userChanged = it.userChange + + // Destroy all tiles that are not in the new set + specsToTiles + .filter { it.key !in newTileList && it.value is TileOrNotInstalled.Tile } + .forEach { entry -> + logger.logTileDestroyed( + entry.key, + if (userChanged) { + QSPipelineLogger.TileDestroyedReason + .TILE_NOT_PRESENT_IN_NEW_USER } else { - // Create tile here will never try to create a CustomTile that - // is not installed - val newTile = - if (tileSpec in specsToTiles) { - processExistingTile( - tileSpec, - specsToTiles.getValue(tileSpec), - userChanged, - newUser - ) - ?: createTile(tileSpec) - } else { - createTile(tileSpec) - } - if (newTile != null) { - newTileMap[tileSpec] = TileOrNotInstalled.Tile(newTile) + QSPipelineLogger.TileDestroyedReason.TILE_REMOVED + } + ) + (entry.value as TileOrNotInstalled.Tile).tile.destroy() + } + // MutableMap will keep the insertion order + val newTileMap = mutableMapOf<TileSpec, TileOrNotInstalled>() + + newTileList.forEach { tileSpec -> + if (tileSpec !in newTileMap) { + if ( + tileSpec is TileSpec.CustomTileSpec && + tileSpec.componentName !in components + ) { + newTileMap[tileSpec] = TileOrNotInstalled.NotInstalled + } else { + // Create tile here will never try to create a CustomTile that + // is not installed + val newTile = + if (tileSpec in specsToTiles) { + processExistingTile( + tileSpec, + specsToTiles.getValue(tileSpec), + userChanged, + newUser + ) ?: createTile(tileSpec) + } else { + createTile(tileSpec) } + if (newTile != null) { + newTileMap[tileSpec] = TileOrNotInstalled.Tile(newTile) } } } + } - val resolvedSpecs = newTileMap.keys.toList() - specsToTiles.clear() - specsToTiles.putAll(newTileMap) - val newResolvedTiles = - newTileMap - .filter { it.value is TileOrNotInstalled.Tile } - .map { - TileModel(it.key, (it.value as TileOrNotInstalled.Tile).tile) - } - - _currentSpecsAndTiles.value = newResolvedTiles - logger.logTilesNotInstalled( - newTileMap.filter { it.value is TileOrNotInstalled.NotInstalled }.keys, - newUser - ) - if (newResolvedTiles.size < minTiles) { - // We ended up with not enough tiles (some may be not installed). - // Prepend the default set of tiles - launch { tileSpecRepository.prependDefault(currentUser.value) } - } else if (resolvedSpecs != newTileList) { - // There were some tiles that couldn't be created. Change the value in - // the - // repository - launch { tileSpecRepository.setTiles(currentUser.value, resolvedSpecs) } - } + val resolvedSpecs = newTileMap.keys.toList() + specsToTiles.clear() + specsToTiles.putAll(newTileMap) + val newResolvedTiles = + newTileMap + .filter { it.value is TileOrNotInstalled.Tile } + .map { TileModel(it.key, (it.value as TileOrNotInstalled.Tile).tile) } + + _currentSpecsAndTiles.value = newResolvedTiles + logger.logTilesNotInstalled( + newTileMap.filter { it.value is TileOrNotInstalled.NotInstalled }.keys, + newUser + ) + if (newResolvedTiles.size < minTiles) { + // We ended up with not enough tiles (some may be not installed). + // Prepend the default set of tiles + launch { tileSpecRepository.prependDefault(currentUser.value) } + } else if (resolvedSpecs != newTileList) { + // There were some tiles that couldn't be created. Change the value in + // the + // repository + launch { tileSpecRepository.setTiles(currentUser.value, resolvedSpecs) } } + } } } } @@ -362,8 +349,7 @@ constructor( newQSTileFactory.get().createTile(spec.spec) } else { null - } - ?: tileFactory.createTile(spec.spec) + } ?: tileFactory.createTile(spec.spec) } if (tile == null) { logger.logTileNotFoundInFactory(spec) @@ -436,15 +422,25 @@ constructor( @JvmInline value class Tile(val tile: QSTile) : TileOrNotInstalled } +} - private data class UserAndTiles( - val userId: Int, - val tiles: List<TileSpec>, - ) - - private data class Data( - val oldData: UserAndTiles, - val newData: UserAndTiles, - val installedComponents: Set<ComponentName>, +private data class UserTilesAndComponents( + val userId: Int, + val tiles: List<TileSpec>, + val installedComponents: Set<ComponentName> +) + +private data class DataWithUserChange( + val userId: Int, + val tiles: List<TileSpec>, + val installedComponents: Set<ComponentName>, + val userChange: Boolean, +) + +private fun DataWithUserChange(data: UserTilesAndComponents, userChange: Boolean) = + DataWithUserChange( + data.userId, + data.tiles, + data.installedComponents, + userChange, ) -} 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 dbfe8188b1b5..abc0453259ce 100644 --- a/packages/SystemUI/src/com/android/systemui/qs/tileimpl/QSTileViewImpl.kt +++ b/packages/SystemUI/src/com/android/systemui/qs/tileimpl/QSTileViewImpl.kt @@ -586,6 +586,15 @@ constructor( ) ) ) + } else { + if (isLongClickable) { + info.addAction( + AccessibilityNodeInfo.AccessibilityAction( + AccessibilityNodeInfo.AccessibilityAction.ACTION_LONG_CLICK.id, + resources.getString(R.string.accessibility_long_click_tile) + ) + ) + } } if (!TextUtils.isEmpty(accessibilityClass)) { info.className = @@ -597,14 +606,6 @@ constructor( if (Switch::class.java.name == accessibilityClass) { info.isChecked = tileState info.isCheckable = true - if (isLongClickable) { - info.addAction( - AccessibilityNodeInfo.AccessibilityAction( - AccessibilityNodeInfo.AccessibilityAction.ACTION_LONG_CLICK.id, - resources.getString(R.string.accessibility_long_click_tile) - ) - ) - } } } if (position != INVALID) { diff --git a/packages/SystemUI/src/com/android/systemui/qs/tileimpl/SubtitleArrayMapping.kt b/packages/SystemUI/src/com/android/systemui/qs/tileimpl/SubtitleArrayMapping.kt index 53594bbb2c84..f702da46717a 100644 --- a/packages/SystemUI/src/com/android/systemui/qs/tileimpl/SubtitleArrayMapping.kt +++ b/packages/SystemUI/src/com/android/systemui/qs/tileimpl/SubtitleArrayMapping.kt @@ -27,7 +27,6 @@ object SubtitleArrayMapping { subtitleIdsMap["cell"] = R.array.tile_states_cell subtitleIdsMap["battery"] = R.array.tile_states_battery subtitleIdsMap["dnd"] = R.array.tile_states_dnd - subtitleIdsMap["modes"] = R.array.tile_states_modes subtitleIdsMap["flashlight"] = R.array.tile_states_flashlight subtitleIdsMap["rotation"] = R.array.tile_states_rotation subtitleIdsMap["bt"] = R.array.tile_states_bt 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 bdf935ef420f..b927134842df 100644 --- a/packages/SystemUI/src/com/android/systemui/qs/tiles/DndTile.java +++ b/packages/SystemUI/src/com/android/systemui/qs/tiles/DndTile.java @@ -49,6 +49,7 @@ import com.android.systemui.animation.DialogTransitionAnimator; import com.android.systemui.animation.Expandable; import com.android.systemui.dagger.qualifiers.Background; import com.android.systemui.dagger.qualifiers.Main; +import com.android.systemui.flags.RefactorFlagUtils; import com.android.systemui.plugins.ActivityStarter; import com.android.systemui.plugins.FalsingManager; import com.android.systemui.plugins.qs.QSTile.BooleanState; @@ -105,6 +106,11 @@ public class DndTile extends QSTileImpl<BooleanState> { ) { super(host, uiEventLogger, backgroundLooper, mainHandler, falsingManager, metricsLogger, statusBarStateController, activityStarter, qsLogger); + + // If the flag is on, this shouldn't run at all since the modes tile replaces the DND tile. + RefactorFlagUtils.INSTANCE.assertInLegacyMode(android.app.Flags.modesUi(), + android.app.Flags.FLAG_MODES_UI); + mController = zenModeController; mSharedPreferences = sharedPreferences; mController.observe(getLifecycle(), mZenCallback); @@ -253,18 +259,20 @@ public class DndTile extends QSTileImpl<BooleanState> { case Global.ZEN_MODE_IMPORTANT_INTERRUPTIONS: state.contentDescription = mContext.getString(R.string.accessibility_quick_settings_dnd) + ", " - + state.secondaryLabel; + + state.secondaryLabel; break; case Global.ZEN_MODE_NO_INTERRUPTIONS: state.contentDescription = mContext.getString(R.string.accessibility_quick_settings_dnd) + ", " + - mContext.getString(R.string.accessibility_quick_settings_dnd_none_on) + mContext.getString( + R.string.accessibility_quick_settings_dnd_none_on) + ", " + state.secondaryLabel; break; case ZEN_MODE_ALARMS: state.contentDescription = mContext.getString(R.string.accessibility_quick_settings_dnd) + ", " + - mContext.getString(R.string.accessibility_quick_settings_dnd_alarms_on) + mContext.getString( + R.string.accessibility_quick_settings_dnd_alarms_on) + ", " + state.secondaryLabel; break; default: diff --git a/packages/SystemUI/src/com/android/systemui/qs/tiles/ModesTile.kt b/packages/SystemUI/src/com/android/systemui/qs/tiles/ModesTile.kt index a3000316057f..2a33a16fa43a 100644 --- a/packages/SystemUI/src/com/android/systemui/qs/tiles/ModesTile.kt +++ b/packages/SystemUI/src/com/android/systemui/qs/tiles/ModesTile.kt @@ -23,13 +23,15 @@ import android.os.Looper import androidx.lifecycle.Lifecycle import androidx.lifecycle.coroutineScope import androidx.lifecycle.repeatOnLifecycle +import com.android.internal.R.attr.contentDescription import com.android.internal.logging.MetricsLogger import com.android.systemui.animation.Expandable import com.android.systemui.dagger.qualifiers.Background import com.android.systemui.dagger.qualifiers.Main +import com.android.systemui.flags.RefactorFlagUtils.isUnexpectedlyInLegacyMode import com.android.systemui.plugins.ActivityStarter import com.android.systemui.plugins.FalsingManager -import com.android.systemui.plugins.qs.QSTile.BooleanState +import com.android.systemui.plugins.qs.QSTile import com.android.systemui.plugins.statusbar.StatusBarStateController import com.android.systemui.qs.QSHost import com.android.systemui.qs.QsEventLogger @@ -63,7 +65,7 @@ constructor( private val tileMapper: ModesTileMapper, private val userActionInteractor: ModesTileUserActionInteractor, ) : - QSTileImpl<BooleanState>( + QSTileImpl<QSTile.State>( host, uiEventLogger, backgroundLooper, @@ -79,6 +81,8 @@ constructor( private val config = qsTileConfigProvider.getConfig(TILE_SPEC) init { + /* Check if */ isUnexpectedlyInLegacyMode(Flags.modesUi(), Flags.FLAG_MODES_UI) + lifecycle.coroutineScope.launch { lifecycle.repeatOnLifecycle(Lifecycle.State.RESUMED) { dataInteractor.tileData().collect { refreshState(it) } @@ -90,7 +94,7 @@ constructor( override fun getTileLabel(): CharSequence = tileState.label - override fun newTileState() = BooleanState() + override fun newTileState() = QSTile.State() override fun handleClick(expandable: Expandable?) = runBlocking { userActionInteractor.handleClick(expandable) @@ -98,22 +102,22 @@ constructor( override fun getLongClickIntent(): Intent = userActionInteractor.longClickIntent - override fun handleUpdateState(booleanState: BooleanState?, arg: Any?) { + override fun handleUpdateState(state: QSTile.State?, arg: Any?) { if (arg is ModesTileModel) { tileState = tileMapper.map(config, arg) - booleanState?.apply { - state = tileState.activationState.legacyState + state?.apply { + this.state = tileState.activationState.legacyState icon = ResourceIcon.get(tileState.iconRes ?: R.drawable.qs_dnd_icon_off) label = tileLabel secondaryLabel = tileState.secondaryLabel contentDescription = tileState.contentDescription - forceExpandIcon = true + expandedAccessibilityClassName = tileState.expandedAccessibilityClassName } } } companion object { - const val TILE_SPEC = "modes" + const val TILE_SPEC = "dnd" } } 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 d9546ec6ac51..1750347fd2ae 100644 --- a/packages/SystemUI/src/com/android/systemui/qs/tiles/WorkModeTile.java +++ b/packages/SystemUI/src/com/android/systemui/qs/tiles/WorkModeTile.java @@ -106,7 +106,8 @@ public class WorkModeTile extends QSTileImpl<BooleanState> implements @Override @MainThread public void onManagedProfileRemoved() { - mHost.removeTile(getTileSpec()); + // No OP as this may race with the user change in CurrentTilesInteractor. + // If the tile needs to be removed, AutoAdd (or AutoTileManager) will take care of that. } @Override diff --git a/packages/SystemUI/src/com/android/systemui/qs/tiles/dialog/InternetDialogController.java b/packages/SystemUI/src/com/android/systemui/qs/tiles/dialog/InternetDialogController.java index 158eb6eb5e89..b2873c5662e7 100644 --- a/packages/SystemUI/src/com/android/systemui/qs/tiles/dialog/InternetDialogController.java +++ b/packages/SystemUI/src/com/android/systemui/qs/tiles/dialog/InternetDialogController.java @@ -736,7 +736,8 @@ public class InternetDialogController implements AccessPointController.AccessPoi // Set network description for the carrier network when connecting to the carrier network // under the airplane mode ON. if (activeNetworkIsCellular() || isCarrierNetworkActive()) { - summary = context.getString(R.string.preference_summary_default_combination, + summary = context.getString( + com.android.settingslib.R.string.preference_summary_default_combination, context.getString( isForDds // if nonDds is active, explains Dds status as poor connection ? (isOnNonDds ? R.string.mobile_data_poor_connection diff --git a/packages/SystemUI/src/com/android/systemui/qs/tiles/impl/modes/domain/interactor/ModesTileDataInteractor.kt b/packages/SystemUI/src/com/android/systemui/qs/tiles/impl/modes/domain/interactor/ModesTileDataInteractor.kt index 31e91aa8fe87..92efa40584e7 100644 --- a/packages/SystemUI/src/com/android/systemui/qs/tiles/impl/modes/domain/interactor/ModesTileDataInteractor.kt +++ b/packages/SystemUI/src/com/android/systemui/qs/tiles/impl/modes/domain/interactor/ModesTileDataInteractor.kt @@ -19,20 +19,27 @@ package com.android.systemui.qs.tiles.impl.modes.domain.interactor import android.app.Flags import android.os.UserHandle import com.android.settingslib.notification.data.repository.ZenModeRepository +import com.android.systemui.dagger.qualifiers.Background import com.android.systemui.qs.tiles.base.interactor.DataUpdateTrigger import com.android.systemui.qs.tiles.base.interactor.QSTileDataInteractor import com.android.systemui.qs.tiles.impl.modes.domain.model.ModesTileModel import javax.inject.Inject +import kotlinx.coroutines.CoroutineDispatcher import kotlinx.coroutines.flow.Flow import kotlinx.coroutines.flow.distinctUntilChanged import kotlinx.coroutines.flow.flowOf +import kotlinx.coroutines.flow.flowOn import kotlinx.coroutines.flow.map -class ModesTileDataInteractor @Inject constructor(val zenModeRepository: ZenModeRepository) : - QSTileDataInteractor<ModesTileModel> { - private val zenModeActive = +class ModesTileDataInteractor +@Inject +constructor( + val zenModeRepository: ZenModeRepository, + @Background val bgDispatcher: CoroutineDispatcher, +) : QSTileDataInteractor<ModesTileModel> { + private val activeModes = zenModeRepository.modes - .map { modes -> modes.any { mode -> mode.isActive } } + .map { modes -> modes.filter { mode -> mode.isActive }.map { it.name } } .distinctUntilChanged() override fun tileData( @@ -45,7 +52,10 @@ class ModesTileDataInteractor @Inject constructor(val zenModeRepository: ZenMode * * TODO(b/299909989): Remove after the transition. */ - fun tileData() = zenModeActive.map { ModesTileModel(isActivated = it) } + fun tileData() = + activeModes + .map { ModesTileModel(isActivated = it.isNotEmpty(), activeModes = it) } + .flowOn(bgDispatcher) override fun availability(user: UserHandle): Flow<Boolean> = flowOf(Flags.modesUi()) } diff --git a/packages/SystemUI/src/com/android/systemui/qs/tiles/impl/modes/domain/model/ModesTileModel.kt b/packages/SystemUI/src/com/android/systemui/qs/tiles/impl/modes/domain/model/ModesTileModel.kt index e44413a962f4..cc509ead3031 100644 --- a/packages/SystemUI/src/com/android/systemui/qs/tiles/impl/modes/domain/model/ModesTileModel.kt +++ b/packages/SystemUI/src/com/android/systemui/qs/tiles/impl/modes/domain/model/ModesTileModel.kt @@ -15,4 +15,4 @@ */ package com.android.systemui.qs.tiles.impl.modes.domain.model -data class ModesTileModel(val isActivated: Boolean) +data class ModesTileModel(val isActivated: Boolean, val activeModes: List<String>) diff --git a/packages/SystemUI/src/com/android/systemui/qs/tiles/impl/modes/ui/ModesTileMapper.kt b/packages/SystemUI/src/com/android/systemui/qs/tiles/impl/modes/ui/ModesTileMapper.kt index 7048adab329d..7afdb75b6dba 100644 --- a/packages/SystemUI/src/com/android/systemui/qs/tiles/impl/modes/ui/ModesTileMapper.kt +++ b/packages/SystemUI/src/com/android/systemui/qs/tiles/impl/modes/ui/ModesTileMapper.kt @@ -17,6 +17,8 @@ package com.android.systemui.qs.tiles.impl.modes.ui import android.content.res.Resources +import android.icu.text.MessageFormat +import android.widget.Button import com.android.systemui.common.shared.model.Icon import com.android.systemui.dagger.qualifiers.Main import com.android.systemui.qs.tiles.base.interactor.QSTileDataToStateMapper @@ -24,6 +26,7 @@ import com.android.systemui.qs.tiles.impl.modes.domain.model.ModesTileModel import com.android.systemui.qs.tiles.viewmodel.QSTileConfig import com.android.systemui.qs.tiles.viewmodel.QSTileState import com.android.systemui.res.R +import java.util.Locale import javax.inject.Inject class ModesTileMapper @@ -46,19 +49,32 @@ constructor( contentDescription = null, ) this.icon = { icon } - if (data.isActivated) { - activationState = QSTileState.ActivationState.ACTIVE - secondaryLabel = "Some modes enabled idk" // TODO(b/346519570) - } else { - activationState = QSTileState.ActivationState.INACTIVE - secondaryLabel = "Off" // TODO(b/346519570) - } - contentDescription = label + activationState = + if (data.isActivated) { + QSTileState.ActivationState.ACTIVE + } else { + QSTileState.ActivationState.INACTIVE + } + secondaryLabel = getModesStatus(data, resources) + contentDescription = "$label. $secondaryLabel" supportedActions = setOf( QSTileState.UserAction.CLICK, QSTileState.UserAction.LONG_CLICK, ) sideViewIcon = QSTileState.SideViewIcon.Chevron + expandedAccessibilityClass = Button::class + } + + private fun getModesStatus(data: ModesTileModel, resources: Resources): String { + val msgFormat = + MessageFormat(resources.getString(R.string.zen_mode_active_modes), Locale.getDefault()) + val count = data.activeModes.count() + val args: MutableMap<String, Any> = HashMap() + args["count"] = count + if (count >= 1) { + args["mode"] = data.activeModes[0] } + return msgFormat.format(args) + } } diff --git a/packages/SystemUI/src/com/android/systemui/qs/tiles/viewmodel/QSTileConfig.kt b/packages/SystemUI/src/com/android/systemui/qs/tiles/viewmodel/QSTileConfig.kt index e9e9d8b0bbfc..cdcefdb50b0f 100644 --- a/packages/SystemUI/src/com/android/systemui/qs/tiles/viewmodel/QSTileConfig.kt +++ b/packages/SystemUI/src/com/android/systemui/qs/tiles/viewmodel/QSTileConfig.kt @@ -22,12 +22,15 @@ import androidx.annotation.StringRes import com.android.internal.logging.InstanceId import com.android.systemui.qs.pipeline.shared.TileSpec -data class QSTileConfig( +data class QSTileConfig +@JvmOverloads +constructor( val tileSpec: TileSpec, val uiConfig: QSTileUIConfig, val instanceId: InstanceId, val metricsSpec: String = tileSpec.spec, val policy: QSTilePolicy = QSTilePolicy.NoRestrictions, + val autoRemoveOnUnavailable: Boolean = true, ) /** @@ -38,6 +41,7 @@ sealed interface QSTileUIConfig { val iconRes: Int @DrawableRes get + val labelRes: Int @StringRes get @@ -48,6 +52,7 @@ sealed interface QSTileUIConfig { data object Empty : QSTileUIConfig { override val iconRes: Int get() = Resources.ID_NULL + override val labelRes: Int get() = Resources.ID_NULL } diff --git a/packages/SystemUI/src/com/android/systemui/qs/tiles/viewmodel/QSTileViewModelAdapter.kt b/packages/SystemUI/src/com/android/systemui/qs/tiles/viewmodel/QSTileViewModelAdapter.kt index ba0a8d694a14..c6f9ae8f4463 100644 --- a/packages/SystemUI/src/com/android/systemui/qs/tiles/viewmodel/QSTileViewModelAdapter.kt +++ b/packages/SystemUI/src/com/android/systemui/qs/tiles/viewmodel/QSTileViewModelAdapter.kt @@ -19,7 +19,6 @@ package com.android.systemui.qs.tiles.viewmodel import android.content.Context import android.os.UserHandle import android.util.Log -import androidx.annotation.GuardedBy import com.android.internal.logging.InstanceId import com.android.systemui.Dumpable import com.android.systemui.animation.Expandable @@ -34,6 +33,7 @@ import dagger.assisted.Assisted import dagger.assisted.AssistedFactory import dagger.assisted.AssistedInject import java.io.PrintWriter +import java.util.concurrent.CopyOnWriteArraySet import java.util.function.Supplier import kotlinx.coroutines.CoroutineScope import kotlinx.coroutines.Job @@ -57,10 +57,8 @@ constructor( private val context get() = qsHost.context - @GuardedBy("callbacks") - private val callbacks: MutableCollection<QSTile.Callback> = mutableSetOf() - @GuardedBy("listeningClients") - private val listeningClients: MutableCollection<Any> = mutableSetOf() + private val callbacks = CopyOnWriteArraySet<QSTile.Callback>() + private val listeningClients = CopyOnWriteArraySet<Any>() // Cancels the jobs when the adapter is no longer alive private var tileAdapterJob: Job? = null @@ -72,7 +70,7 @@ constructor( applicationScope.launch { launch { qsTileViewModel.isAvailable.collectIndexed { index, isAvailable -> - if (!isAvailable) { + if (!isAvailable && qsTileViewModel.config.autoRemoveOnUnavailable) { qsHost.removeTile(tileSpec) } // qsTileViewModel.isAvailable flow often starts with isAvailable == true. @@ -113,19 +111,17 @@ constructor( override fun addCallback(callback: QSTile.Callback?) { callback ?: return - synchronized(callbacks) { - callbacks.add(callback) - state?.let(callback::onStateChanged) - } + callbacks.add(callback) + state?.let(callback::onStateChanged) } override fun removeCallback(callback: QSTile.Callback?) { callback ?: return - synchronized(callbacks) { callbacks.remove(callback) } + callbacks.remove(callback) } override fun removeCallbacks() { - synchronized(callbacks) { callbacks.clear() } + callbacks.clear() } override fun click(expandable: Expandable?) { @@ -163,32 +159,28 @@ constructor( override fun setListening(client: Any?, listening: Boolean) { client ?: return - synchronized(listeningClients) { - if (listening) { - listeningClients.add(client) - if (listeningClients.size == 1) { - stateJob = - qsTileViewModel.state - .filterNotNull() - .map { mapState(context, it, qsTileViewModel.config) } - .onEach { legacyState -> - synchronized(callbacks) { - callbacks.forEach { it.onStateChanged(legacyState) } - } - } - .launchIn(applicationScope) - } - } else { - listeningClients.remove(client) - if (listeningClients.isEmpty()) { - stateJob?.cancel() - } + if (listening) { + listeningClients.add(client) + if (listeningClients.size == 1) { + stateJob = + qsTileViewModel.state + .filterNotNull() + .map { mapState(context, it, qsTileViewModel.config) } + .onEach { legacyState -> + callbacks.forEach { it.onStateChanged(legacyState) } + } + .launchIn(applicationScope) + } + } else { + listeningClients.remove(client) + if (listeningClients.isEmpty()) { + stateJob?.cancel() } } } override fun isListening(): Boolean = - synchronized(listeningClients) { listeningClients.isNotEmpty() } + listeningClients.isNotEmpty() override fun setDetailListening(show: Boolean) { // do nothing like QSTileImpl diff --git a/packages/SystemUI/src/com/android/systemui/qs/ui/adapter/QSSceneAdapter.kt b/packages/SystemUI/src/com/android/systemui/qs/ui/adapter/QSSceneAdapter.kt index bb36fd5ea979..ae2f32aae874 100644 --- a/packages/SystemUI/src/com/android/systemui/qs/ui/adapter/QSSceneAdapter.kt +++ b/packages/SystemUI/src/com/android/systemui/qs/ui/adapter/QSSceneAdapter.kt @@ -24,6 +24,7 @@ import androidx.annotation.VisibleForTesting import androidx.asynclayoutinflater.view.AsyncLayoutInflater import com.android.settingslib.applications.InterestingConfigChanges import com.android.systemui.Dumpable +import com.android.systemui.biometrics.domain.interactor.DisplayStateInteractor import com.android.systemui.common.ui.domain.interactor.ConfigurationInteractor import com.android.systemui.dagger.SysUISingleton import com.android.systemui.dagger.qualifiers.Application @@ -196,6 +197,7 @@ constructor( private val qsSceneComponentFactory: QSSceneComponent.Factory, private val qsImplProvider: Provider<QSImpl>, shadeInteractor: ShadeInteractor, + displayStateInteractor: DisplayStateInteractor, dumpManager: DumpManager, @Main private val mainDispatcher: CoroutineDispatcher, @Application applicationScope: CoroutineScope, @@ -208,6 +210,7 @@ constructor( qsSceneComponentFactory: QSSceneComponent.Factory, qsImplProvider: Provider<QSImpl>, shadeInteractor: ShadeInteractor, + displayStateInteractor: DisplayStateInteractor, dumpManager: DumpManager, @Main dispatcher: CoroutineDispatcher, @Application scope: CoroutineScope, @@ -216,6 +219,7 @@ constructor( qsSceneComponentFactory, qsImplProvider, shadeInteractor, + displayStateInteractor, dumpManager, dispatcher, scope, @@ -319,6 +323,10 @@ constructor( qsImpl.value?.setInSplitShade(it == ShadeMode.Split) } } + launch { + combine(displayStateInteractor.isLargeScreen, qsImpl.filterNotNull(), ::Pair) + .collect { it.second.setIsNotificationPanelFullWidth(!it.first) } + } } } diff --git a/packages/SystemUI/src/com/android/systemui/scene/domain/startable/SceneContainerStartable.kt b/packages/SystemUI/src/com/android/systemui/scene/domain/startable/SceneContainerStartable.kt index 3fca84efdd05..5b5013352c29 100644 --- a/packages/SystemUI/src/com/android/systemui/scene/domain/startable/SceneContainerStartable.kt +++ b/packages/SystemUI/src/com/android/systemui/scene/domain/startable/SceneContainerStartable.kt @@ -172,12 +172,28 @@ constructor( private fun resetShadeSessions() { applicationScope.launch { - sceneBackInteractor.backStack - // We are in a session if either Shade or QuickSettings is on the back stack - .map { backStack -> - backStack.asIterable().any { it == Scenes.Shade || it == Scenes.QuickSettings } + combine( + sceneBackInteractor.backStack + // We are in a session if either Shade or QuickSettings is on the back stack + .map { backStack -> + backStack.asIterable().any { + it == Scenes.Shade || it == Scenes.QuickSettings + } + } + .distinctUntilChanged(), + sceneInteractor.transitionState + .mapNotNull { state -> + // We are also in a session if either Shade or QuickSettings is the + // current scene + when (state) { + is ObservableTransitionState.Idle -> state.currentScene + is ObservableTransitionState.Transition -> state.fromScene + }.let { it == Scenes.Shade || it == Scenes.QuickSettings } + } + .distinctUntilChanged() + ) { inBackStack, isCurrentScene -> + inBackStack || isCurrentScene } - .distinctUntilChanged() // Once a session has ended, clear the session storage. .filter { inSession -> !inSession } .collect { shadeSessionStorage.clear() } diff --git a/packages/SystemUI/src/com/android/systemui/screenshot/LegacyScreenshotController.java b/packages/SystemUI/src/com/android/systemui/screenshot/LegacyScreenshotController.java index a2583e6cc08b..bc8642c67fb4 100644 --- a/packages/SystemUI/src/com/android/systemui/screenshot/LegacyScreenshotController.java +++ b/packages/SystemUI/src/com/android/systemui/screenshot/LegacyScreenshotController.java @@ -35,7 +35,6 @@ import android.animation.AnimatorListenerAdapter; import android.annotation.MainThread; import android.annotation.NonNull; import android.annotation.Nullable; -import android.app.ICompatCameraControlCallback; import android.content.BroadcastReceiver; import android.content.Context; import android.content.Intent; @@ -492,13 +491,6 @@ public class LegacyScreenshotController implements InteractiveScreenshotHandler } } } - - @Override - public void requestCompatCameraControl(boolean showControl, - boolean transformationApplied, - ICompatCameraControlCallback callback) { - Log.w(TAG, "Unexpected requestCompatCameraControl callback"); - } }); }); } diff --git a/packages/SystemUI/src/com/android/systemui/screenshot/ScreenshotController.java b/packages/SystemUI/src/com/android/systemui/screenshot/ScreenshotController.java index 653e49ffb08d..ec529cd6fa52 100644 --- a/packages/SystemUI/src/com/android/systemui/screenshot/ScreenshotController.java +++ b/packages/SystemUI/src/com/android/systemui/screenshot/ScreenshotController.java @@ -35,7 +35,6 @@ import android.animation.AnimatorListenerAdapter; import android.annotation.MainThread; import android.annotation.NonNull; import android.annotation.Nullable; -import android.app.ICompatCameraControlCallback; import android.content.BroadcastReceiver; import android.content.Context; import android.content.Intent; @@ -492,13 +491,6 @@ public class ScreenshotController implements InteractiveScreenshotHandler { } } } - - @Override - public void requestCompatCameraControl(boolean showControl, - boolean transformationApplied, - ICompatCameraControlCallback callback) { - Log.w(TAG, "Unexpected requestCompatCameraControl callback"); - } }); }); } diff --git a/packages/SystemUI/src/com/android/systemui/settings/SystemSettingsRepositoryModule.kt b/packages/SystemUI/src/com/android/systemui/settings/SystemSettingsRepositoryModule.kt new file mode 100644 index 000000000000..02ce74a94de6 --- /dev/null +++ b/packages/SystemUI/src/com/android/systemui/settings/SystemSettingsRepositoryModule.kt @@ -0,0 +1,38 @@ +/* + * Copyright (C) 2024 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.android.systemui.settings + +import android.content.ContentResolver +import com.android.systemui.dagger.SysUISingleton +import com.android.systemui.dagger.qualifiers.Background +import com.android.systemui.shared.settings.data.repository.SystemSettingsRepository +import com.android.systemui.shared.settings.data.repository.SystemSettingsRepositoryImpl +import dagger.Module +import dagger.Provides +import kotlinx.coroutines.CoroutineDispatcher + +@Module +object SystemSettingsRepositoryModule { + @JvmStatic + @Provides + @SysUISingleton + fun provideSystemSettingsRepository( + contentResolver: ContentResolver, + @Background backgroundDispatcher: CoroutineDispatcher, + ): SystemSettingsRepository = + SystemSettingsRepositoryImpl(contentResolver, backgroundDispatcher) +} diff --git a/packages/SystemUI/src/com/android/systemui/shade/NotificationShadeWindowControllerImpl.java b/packages/SystemUI/src/com/android/systemui/shade/NotificationShadeWindowControllerImpl.java index bc5cf2a87925..7e0454c1fa2a 100644 --- a/packages/SystemUI/src/com/android/systemui/shade/NotificationShadeWindowControllerImpl.java +++ b/packages/SystemUI/src/com/android/systemui/shade/NotificationShadeWindowControllerImpl.java @@ -41,12 +41,13 @@ import android.view.IWindowSession; import android.view.View; import android.view.ViewGroup; import android.view.WindowInsets; -import android.view.WindowManager; import android.view.WindowManager.LayoutParams; import android.view.WindowManagerGlobal; +import com.android.app.viewcapture.ViewCaptureAwareWindowManager; import com.android.internal.annotations.VisibleForTesting; import com.android.systemui.Dumpable; +import com.android.systemui.Flags; import com.android.systemui.biometrics.AuthController; import com.android.systemui.colorextraction.SysuiColorExtractor; import com.android.systemui.communal.domain.interactor.CommunalInteractor; @@ -63,6 +64,7 @@ import com.android.systemui.scene.shared.flag.SceneContainerFlag; import com.android.systemui.scene.ui.view.WindowRootViewComponent; import com.android.systemui.settings.UserTracker; import com.android.systemui.shade.domain.interactor.ShadeInteractor; +import com.android.systemui.shade.ui.viewmodel.NotificationShadeWindowModel; import com.android.systemui.statusbar.NotificationShadeWindowController; import com.android.systemui.statusbar.StatusBarState; import com.android.systemui.statusbar.SysuiStatusBarStateController; @@ -101,7 +103,7 @@ public class NotificationShadeWindowControllerImpl implements NotificationShadeW private final Context mContext; private final WindowRootViewComponent.Factory mWindowRootViewComponentFactory; - private final WindowManager mWindowManager; + private final ViewCaptureAwareWindowManager mWindowManager; private final IActivityManager mActivityManager; private final DozeParameters mDozeParameters; private final KeyguardStateController mKeyguardStateController; @@ -130,6 +132,7 @@ public class NotificationShadeWindowControllerImpl implements NotificationShadeW mCallbacks = new ArrayList<>(); private final SysuiColorExtractor mColorExtractor; + private final NotificationShadeWindowModel mNotificationShadeWindowModel; /** * Layout params would be aggregated and dispatched all at once if this is > 0. * @@ -145,7 +148,7 @@ public class NotificationShadeWindowControllerImpl implements NotificationShadeW public NotificationShadeWindowControllerImpl( Context context, WindowRootViewComponent.Factory windowRootViewComponentFactory, - WindowManager windowManager, + ViewCaptureAwareWindowManager viewCaptureAwareWindowManager, IActivityManager activityManager, DozeParameters dozeParameters, StatusBarStateController statusBarStateController, @@ -162,10 +165,11 @@ public class NotificationShadeWindowControllerImpl implements NotificationShadeW ShadeWindowLogger logger, Lazy<SelectedUserInteractor> userInteractor, UserTracker userTracker, + NotificationShadeWindowModel notificationShadeWindowModel, Lazy<CommunalInteractor> communalInteractor) { mContext = context; mWindowRootViewComponentFactory = windowRootViewComponentFactory; - mWindowManager = windowManager; + mWindowManager = viewCaptureAwareWindowManager; mActivityManager = activityManager; mDozeParameters = dozeParameters; mKeyguardStateController = keyguardStateController; @@ -176,6 +180,7 @@ public class NotificationShadeWindowControllerImpl implements NotificationShadeW mKeyguardBypassController = keyguardBypassController; mBackgroundExecutor = backgroundExecutor; mColorExtractor = colorExtractor; + mNotificationShadeWindowModel = notificationShadeWindowModel; // prefix with {slow} to make sure this dumps at the END of the critical section. dumpManager.registerCriticalDumpable("{slow}NotificationShadeWindowControllerImpl", this); mAuthController = authController; @@ -329,6 +334,14 @@ public class NotificationShadeWindowControllerImpl implements NotificationShadeW mCommunalInteractor.get().isCommunalVisible(), this::onCommunalVisibleChanged ); + + if (!SceneContainerFlag.isEnabled() && Flags.useTransitionsForKeyguardOccluded()) { + collectFlow( + mWindowRootView, + mNotificationShadeWindowModel.isKeyguardOccluded(), + this::setKeyguardOccluded + ); + } } @Override @@ -341,6 +354,11 @@ public class NotificationShadeWindowControllerImpl implements NotificationShadeW mScreenBrightnessDoze = value / 255f; } + @Override + public void setDozeScreenBrightnessFloat(float value) { + mScreenBrightnessDoze = value; + } + private void setKeyguardDark(boolean dark) { int vis = mWindowRootView.getSystemUiVisibility(); if (dark) { diff --git a/packages/SystemUI/src/com/android/systemui/shade/domain/startable/ShadeStartable.kt b/packages/SystemUI/src/com/android/systemui/shade/domain/startable/ShadeStartable.kt index 5eb3a1cc1348..330f53fc3701 100644 --- a/packages/SystemUI/src/com/android/systemui/shade/domain/startable/ShadeStartable.kt +++ b/packages/SystemUI/src/com/android/systemui/shade/domain/startable/ShadeStartable.kt @@ -18,6 +18,7 @@ package com.android.systemui.shade.domain.startable import android.content.Context import com.android.systemui.CoreStartable +import com.android.systemui.biometrics.domain.interactor.DisplayStateInteractor import com.android.systemui.common.ui.data.repository.ConfigurationRepository import com.android.systemui.dagger.SysUISingleton import com.android.systemui.dagger.qualifiers.Application @@ -32,6 +33,7 @@ import com.android.systemui.shade.domain.interactor.PanelExpansionInteractor import com.android.systemui.shade.transition.ScrimShadeTransitionController import com.android.systemui.statusbar.PulseExpansionHandler import com.android.systemui.statusbar.notification.stack.NotificationStackScrollLayoutController +import com.android.systemui.statusbar.phone.ScrimController import com.android.systemui.statusbar.policy.SplitShadeStateController import javax.inject.Inject import javax.inject.Provider @@ -56,11 +58,14 @@ constructor( private val panelExpansionInteractorProvider: Provider<PanelExpansionInteractor>, private val shadeExpansionStateManager: ShadeExpansionStateManager, private val pulseExpansionHandler: PulseExpansionHandler, + private val displayStateInteractor: DisplayStateInteractor, private val nsslc: NotificationStackScrollLayoutController, + private val scrimController: ScrimController, ) : CoreStartable { override fun start() { hydrateShadeLayoutWidth() + hydrateFullWidth() hydrateShadeExpansionStateManager() logTouchesTo(touchLog) scrimShadeTransitionController.init() @@ -98,4 +103,16 @@ constructor( } } } + + private fun hydrateFullWidth() { + if (SceneContainerFlag.isEnabled) { + applicationScope.launch { + displayStateInteractor.isLargeScreen.collect { + val isFullWidth = !it + nsslc.setIsFullWidth(isFullWidth) + scrimController.setClipsQsScrim(isFullWidth) + } + } + } + } } diff --git a/packages/SystemUI/src/com/android/systemui/shade/ui/viewmodel/NotificationShadeWindowModel.kt b/packages/SystemUI/src/com/android/systemui/shade/ui/viewmodel/NotificationShadeWindowModel.kt new file mode 100644 index 000000000000..e1289af58f06 --- /dev/null +++ b/packages/SystemUI/src/com/android/systemui/shade/ui/viewmodel/NotificationShadeWindowModel.kt @@ -0,0 +1,35 @@ +/* + * Copyright (C) 2024 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.android.systemui.shade.ui.viewmodel + +import com.android.systemui.dagger.SysUISingleton +import com.android.systemui.keyguard.domain.interactor.KeyguardTransitionInteractor +import com.android.systemui.keyguard.shared.model.KeyguardState.OCCLUDED +import javax.inject.Inject +import kotlinx.coroutines.flow.Flow +import kotlinx.coroutines.flow.map + +/** Models UI state for the shade window. */ +@SysUISingleton +class NotificationShadeWindowModel +@Inject +constructor( + keyguardTransitionInteractor: KeyguardTransitionInteractor, +) { + val isKeyguardOccluded: Flow<Boolean> = + keyguardTransitionInteractor.transitionValue(OCCLUDED).map { it == 1f } +} diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/NotificationShadeWindowController.java b/packages/SystemUI/src/com/android/systemui/statusbar/NotificationShadeWindowController.java index 707d59aa560d..85fad420daf1 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/NotificationShadeWindowController.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/NotificationShadeWindowController.java @@ -131,10 +131,20 @@ public interface NotificationShadeWindowController extends RemoteInputController /** Sets the state of whether the remote input is active or not. */ default void onRemoteInputActive(boolean remoteInputActive) {} - /** Sets the screen brightness level for when the device is dozing. */ + /** + * Sets the screen brightness level for when the device is dozing. + * @param value The brightness value between 1 and 255 + */ default void setDozeScreenBrightness(int value) {} /** + * Sets the screen brightness level for when the device is dozing. + * @param value The brightness value between {@link PowerManager#BRIGHTNESS_MIN} and + * {@link PowerManager#BRIGHTNESS_MAX} + */ + default void setDozeScreenBrightnessFloat(float value) {} + + /** * Sets whether the screen brightness is forced to the value we use for doze mode by the status * bar window. No-op if the device does not support dozing. */ diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/coordinator/HeadsUpCoordinator.kt b/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/coordinator/HeadsUpCoordinator.kt index aff57bd076c5..e50d64bcb8f9 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/coordinator/HeadsUpCoordinator.kt +++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/coordinator/HeadsUpCoordinator.kt @@ -50,10 +50,10 @@ import java.util.function.Consumer import javax.inject.Inject /** - * Coordinates heads up notification (HUN) interactions with the notification pipeline based on - * the HUN state reported by the [HeadsUpManager]. In this class we only consider one - * notification, in particular the [HeadsUpManager.getTopEntry], to be HeadsUpping at a - * time even though other notifications may be queued to heads up next. + * Coordinates heads up notification (HUN) interactions with the notification pipeline based on the + * HUN state reported by the [HeadsUpManager]. In this class we only consider one notification, in + * particular the [HeadsUpManager.getTopEntry], to be HeadsUpping at a time even though other + * notifications may be queued to heads up next. * * The current HUN, but not HUNs that are queued to heads up, will be: * - Lifetime extended until it's no longer heads upping. @@ -64,7 +64,9 @@ import javax.inject.Inject * Note: The inflation callback in [PreparationCoordinator] handles showing HUNs. */ @CoordinatorScope -class HeadsUpCoordinator @Inject constructor( +class HeadsUpCoordinator +@Inject +constructor( private val mLogger: HeadsUpCoordinatorLogger, private val mSystemClock: SystemClock, private val mHeadsUpManager: HeadsUpManager, @@ -104,8 +106,8 @@ class HeadsUpCoordinator @Inject constructor( } /** - * Once the pipeline starts running, we can look through posted entries and quickly process - * any that don't have groups, and thus will never gave a group heads up edge case. + * Once the pipeline starts running, we can look through posted entries and quickly process any + * that don't have groups, and thus will never gave a group heads up edge case. */ fun onBeforeTransformGroups(list: List<ListEntry>) { mNow = mSystemClock.currentTimeMillis() @@ -128,120 +130,137 @@ class HeadsUpCoordinator @Inject constructor( * we know that stability and [NotifPromoter]s have been applied, so we can use the location of * notifications in this list to determine what kind of group heads up behavior should happen. */ - fun onBeforeFinalizeFilter(list: List<ListEntry>) = mHeadsUpManager.modifyHuns { hunMutator -> - // Nothing to do if there are no other adds/updates - if (mPostedEntries.isEmpty()) { - return@modifyHuns - } - // Calculate a bunch of information about the logical group and the locations of group - // entries in the nearly-finalized shade list. These may be used in the per-group loop. - val postedEntriesByGroup = mPostedEntries.values.groupBy { it.entry.sbn.groupKey } - val logicalMembersByGroup = mNotifPipeline.allNotifs.asSequence() - .filter { postedEntriesByGroup.contains(it.sbn.groupKey) } - .groupBy { it.sbn.groupKey } - val groupLocationsByKey: Map<String, GroupLocation> by lazy { getGroupLocationsByKey(list) } - mLogger.logEvaluatingGroups(postedEntriesByGroup.size) - // For each group, determine which notification(s) for a group should heads up. - postedEntriesByGroup.forEach { (groupKey, postedEntries) -> - // get and classify the logical members - val logicalMembers = logicalMembersByGroup[groupKey] ?: emptyList() - val logicalSummary = logicalMembers.find { it.sbn.notification.isGroupSummary } - - // Report the start of this group's evaluation - mLogger.logEvaluatingGroup(groupKey, postedEntries.size, logicalMembers.size) - - // If there is no logical summary, then there is no heads up to transfer - if (logicalSummary == null) { - postedEntries.forEach { - handlePostedEntry(it, hunMutator, scenario = "logical-summary-missing") - } - return@forEach + fun onBeforeFinalizeFilter(list: List<ListEntry>) = + mHeadsUpManager.modifyHuns { hunMutator -> + // Nothing to do if there are no other adds/updates + if (mPostedEntries.isEmpty()) { + return@modifyHuns } + // Calculate a bunch of information about the logical group and the locations of group + // entries in the nearly-finalized shade list. These may be used in the per-group loop. + val postedEntriesByGroup = mPostedEntries.values.groupBy { it.entry.sbn.groupKey } + val logicalMembersByGroup = + mNotifPipeline.allNotifs + .asSequence() + .filter { postedEntriesByGroup.contains(it.sbn.groupKey) } + .groupBy { it.sbn.groupKey } + val groupLocationsByKey: Map<String, GroupLocation> by lazy { + getGroupLocationsByKey(list) + } + mLogger.logEvaluatingGroups(postedEntriesByGroup.size) + // For each group, determine which notification(s) for a group should heads up. + postedEntriesByGroup.forEach { (groupKey, postedEntries) -> + // get and classify the logical members + val logicalMembers = logicalMembersByGroup[groupKey] ?: emptyList() + val logicalSummary = logicalMembers.find { it.sbn.notification.isGroupSummary } + + // Report the start of this group's evaluation + mLogger.logEvaluatingGroup(groupKey, postedEntries.size, logicalMembers.size) + + // If there is no logical summary, then there is no heads up to transfer + if (logicalSummary == null) { + postedEntries.forEach { + handlePostedEntry(it, hunMutator, scenario = "logical-summary-missing") + } + return@forEach + } - // If summary isn't wanted to be heads up, then there is no heads up to transfer - if (!isGoingToShowHunStrict(logicalSummary)) { - postedEntries.forEach { - handlePostedEntry(it, hunMutator, scenario = "logical-summary-not-heads-up") + // If summary isn't wanted to be heads up, then there is no heads up to transfer + if (!isGoingToShowHunStrict(logicalSummary)) { + postedEntries.forEach { + handlePostedEntry(it, hunMutator, scenario = "logical-summary-not-heads-up") + } + return@forEach } - return@forEach - } - // The group is heads up! Overall goals: - // - Maybe transfer its heads up to a child - // - Also let any/all newly heads up children still heads up - var childToReceiveParentHeadsUp: NotificationEntry? - var targetType = "undefined" - - // If the parent is heads up, always look at the posted notification with the newest - // 'when', and if it is isolated with GROUP_ALERT_SUMMARY, then it should receive the - // parent's heads up. - childToReceiveParentHeadsUp = - findHeadsUpOverride(postedEntries, groupLocationsByKey::getLocation) - if (childToReceiveParentHeadsUp != null) { - targetType = "headsUpOverride" - } + // The group is heads up! Overall goals: + // - Maybe transfer its heads up to a child + // - Also let any/all newly heads up children still heads up + var childToReceiveParentHeadsUp: NotificationEntry? + var targetType = "undefined" - // If the summary is Detached and we have not picked a receiver of the heads up, then we - // need to look for the best child to heads up in place of the summary. - val isSummaryAttached = groupLocationsByKey.contains(logicalSummary.key) - if (!isSummaryAttached && childToReceiveParentHeadsUp == null) { + // If the parent is heads up, always look at the posted notification with the newest + // 'when', and if it is isolated with GROUP_ALERT_SUMMARY, then it should receive + // the + // parent's heads up. childToReceiveParentHeadsUp = - findBestTransferChild(logicalMembers, groupLocationsByKey::getLocation) + findHeadsUpOverride(postedEntries, groupLocationsByKey::getLocation) if (childToReceiveParentHeadsUp != null) { - targetType = "bestChild" + targetType = "headsUpOverride" } - } - // If there is no child to receive the parent heads up, then just handle the posted - // entries and return. - if (childToReceiveParentHeadsUp == null) { - postedEntries.forEach { - handlePostedEntry(it, hunMutator, scenario = "no-transfer-target") + // If the summary is Detached and we have not picked a receiver of the heads up, + // then we + // need to look for the best child to heads up in place of the summary. + val isSummaryAttached = groupLocationsByKey.contains(logicalSummary.key) + if (!isSummaryAttached && childToReceiveParentHeadsUp == null) { + childToReceiveParentHeadsUp = + findBestTransferChild(logicalMembers, groupLocationsByKey::getLocation) + if (childToReceiveParentHeadsUp != null) { + targetType = "bestChild" + } } - return@forEach - } - // At this point we just need to initiate the transfer - val summaryUpdate = mPostedEntries[logicalSummary.key] - - // Because we now know for certain that some child is going to heads up for this summary - // (as we have found a child to transfer the heads up to), mark the group as having - // interrupted. This will allow us to know in the future that the "should heads up" - // state of this group has already been handled, just not via the summary entry itself. - logicalSummary.setInterruption() - mLogger.logSummaryMarkedInterrupted(logicalSummary.key, childToReceiveParentHeadsUp.key) - - // If the summary was not attached, then remove the heads up from the detached summary. - // Otherwise we can simply ignore its posted update. - if (!isSummaryAttached) { - val summaryUpdateForRemoval = summaryUpdate?.also { - it.shouldHeadsUpEver = false - } ?: PostedEntry( - logicalSummary, - wasAdded = false, - wasUpdated = false, - shouldHeadsUpEver = false, - shouldHeadsUpAgain = false, - isHeadsUpEntry = mHeadsUpManager.isHeadsUpEntry(logicalSummary.key), - isBinding = isEntryBinding(logicalSummary), + // If there is no child to receive the parent heads up, then just handle the posted + // entries and return. + if (childToReceiveParentHeadsUp == null) { + postedEntries.forEach { + handlePostedEntry(it, hunMutator, scenario = "no-transfer-target") + } + return@forEach + } + + // At this point we just need to initiate the transfer + val summaryUpdate = mPostedEntries[logicalSummary.key] + + // Because we now know for certain that some child is going to heads up for this + // summary + // (as we have found a child to transfer the heads up to), mark the group as having + // interrupted. This will allow us to know in the future that the "should heads up" + // state of this group has already been handled, just not via the summary entry + // itself. + logicalSummary.setInterruption() + mLogger.logSummaryMarkedInterrupted( + logicalSummary.key, + childToReceiveParentHeadsUp.key ) - // If we transfer the heads up notification and the summary isn't even attached, - // that means we should ensure the summary is no longer a heads up notification, - // so we remove it here. - handlePostedEntry( + + // If the summary was not attached, then remove the heads up from the detached + // summary. + // Otherwise we can simply ignore its posted update. + if (!isSummaryAttached) { + val summaryUpdateForRemoval = + summaryUpdate?.also { it.shouldHeadsUpEver = false } + ?: PostedEntry( + logicalSummary, + wasAdded = false, + wasUpdated = false, + shouldHeadsUpEver = false, + shouldHeadsUpAgain = false, + isHeadsUpEntry = mHeadsUpManager.isHeadsUpEntry(logicalSummary.key), + isBinding = isEntryBinding(logicalSummary), + ) + // If we transfer the heads up notification and the summary isn't even attached, + // that means we should ensure the summary is no longer a heads up notification, + // so we remove it here. + handlePostedEntry( summaryUpdateForRemoval, hunMutator, - scenario = "detached-summary-remove-heads-up") - } else if (summaryUpdate != null) { - mLogger.logPostedEntryWillNotEvaluate( + scenario = "detached-summary-remove-heads-up" + ) + } else if (summaryUpdate != null) { + mLogger.logPostedEntryWillNotEvaluate( summaryUpdate, - reason = "attached-summary-transferred") - } + reason = "attached-summary-transferred" + ) + } - // Handle all posted entries -- if the child receiving the parent's heads up is in the - // list, then set its flags to ensure it heads up. - var didHeadsUpChildToReceiveParentHeadsUp = false - postedEntries.asSequence() + // Handle all posted entries -- if the child receiving the parent's heads up is in + // the + // list, then set its flags to ensure it heads up. + var didHeadsUpChildToReceiveParentHeadsUp = false + postedEntries + .asSequence() .filter { it.key != logicalSummary.key } .forEach { postedEntry -> if (childToReceiveParentHeadsUp.key == postedEntry.key) { @@ -249,44 +268,49 @@ class HeadsUpCoordinator @Inject constructor( postedEntry.shouldHeadsUpEver = true postedEntry.shouldHeadsUpAgain = true handlePostedEntry( - postedEntry, - hunMutator, - scenario = "child-heads-up-transfer-target-$targetType") + postedEntry, + hunMutator, + scenario = "child-heads-up-transfer-target-$targetType" + ) didHeadsUpChildToReceiveParentHeadsUp = true } else { handlePostedEntry( - postedEntry, - hunMutator, - scenario = "child-heads-up-non-target") + postedEntry, + hunMutator, + scenario = "child-heads-up-non-target" + ) } } - // If the child receiving the heads up notification was not updated on this tick - // (which can happen in a standard heads up transfer scenario), then construct an update - // so that we can apply it. - if (!didHeadsUpChildToReceiveParentHeadsUp) { - val posted = PostedEntry( - childToReceiveParentHeadsUp, - wasAdded = false, - wasUpdated = false, - shouldHeadsUpEver = true, - shouldHeadsUpAgain = true, - isHeadsUpEntry = + // If the child receiving the heads up notification was not updated on this tick + // (which can happen in a standard heads up transfer scenario), then construct an + // update + // so that we can apply it. + if (!didHeadsUpChildToReceiveParentHeadsUp) { + val posted = + PostedEntry( + childToReceiveParentHeadsUp, + wasAdded = false, + wasUpdated = false, + shouldHeadsUpEver = true, + shouldHeadsUpAgain = true, + isHeadsUpEntry = mHeadsUpManager.isHeadsUpEntry(childToReceiveParentHeadsUp.key), - isBinding = isEntryBinding(childToReceiveParentHeadsUp), - ) - handlePostedEntry( + isBinding = isEntryBinding(childToReceiveParentHeadsUp), + ) + handlePostedEntry( posted, hunMutator, - scenario = "non-posted-child-heads-up-transfer-target-$targetType") + scenario = "non-posted-child-heads-up-transfer-target-$targetType" + ) + } } - } - // After this method runs, all posted entries should have been handled (or skipped). - mPostedEntries.clear() + // After this method runs, all posted entries should have been handled (or skipped). + mPostedEntries.clear() - // Also take this opportunity to clean up any stale entry update times - cleanUpEntryTimes() - } + // Also take this opportunity to clean up any stale entry update times + cleanUpEntryTimes() + } /** * Find the posted child with the newest when, and return it if it is isolated and has @@ -295,34 +319,38 @@ class HeadsUpCoordinator @Inject constructor( private fun findHeadsUpOverride( postedEntries: List<PostedEntry>, locationLookupByKey: (String) -> GroupLocation, - ): NotificationEntry? = postedEntries.asSequence() - .filter { posted -> !posted.entry.sbn.notification.isGroupSummary } - .sortedBy { posted -> - -posted.entry.sbn.notification.getWhen() - } - .firstOrNull() - ?.let { posted -> - posted.entry.takeIf { entry -> - locationLookupByKey(entry.key) == GroupLocation.Isolated && + ): NotificationEntry? = + postedEntries + .asSequence() + .filter { posted -> !posted.entry.sbn.notification.isGroupSummary } + .sortedBy { posted -> -posted.entry.sbn.notification.getWhen() } + .firstOrNull() + ?.let { posted -> + posted.entry.takeIf { entry -> + locationLookupByKey(entry.key) == GroupLocation.Isolated && entry.sbn.notification.groupAlertBehavior == GROUP_ALERT_SUMMARY + } } - } /** - * Of children which are attached, look for the child to receive the notification: - * First prefer children which were updated, then looking for the ones with the newest 'when' + * Of children which are attached, look for the child to receive the notification: First prefer + * children which were updated, then looking for the ones with the newest 'when' */ private fun findBestTransferChild( logicalMembers: List<NotificationEntry>, locationLookupByKey: (String) -> GroupLocation, - ): NotificationEntry? = logicalMembers.asSequence() - .filter { !it.sbn.notification.isGroupSummary } - .filter { locationLookupByKey(it.key) != GroupLocation.Detached } - .sortedWith(compareBy( - { !mPostedEntries.contains(it.key) }, - { -it.sbn.notification.getWhen() }, - )) - .firstOrNull() + ): NotificationEntry? = + logicalMembers + .asSequence() + .filter { !it.sbn.notification.isGroupSummary } + .filter { locationLookupByKey(it.key) != GroupLocation.Detached } + .sortedWith( + compareBy( + { !mPostedEntries.contains(it.key) }, + { -it.sbn.notification.getWhen() }, + ) + ) + .firstOrNull() private fun getGroupLocationsByKey(list: List<ListEntry>): Map<String, GroupLocation> = mutableMapOf<String, GroupLocation>().also { map -> @@ -387,197 +415,217 @@ class HeadsUpCoordinator @Inject constructor( mHeadsUpViewBinder.bindHeadsUpView(posted.entry, this::onHeadsUpViewBound) } - private val mNotifCollectionListener = object : NotifCollectionListener { - /** - * Notification was just added and if it should heads up, bind the view and then show it. - */ - override fun onEntryAdded(entry: NotificationEntry) { - // First check whether this notification should launch a full screen intent, and - // launch it if needed. - val fsiDecision = - mVisualInterruptionDecisionProvider.makeUnloggedFullScreenIntentDecision(entry) - mVisualInterruptionDecisionProvider.logFullScreenIntentDecision(fsiDecision) - if (fsiDecision.shouldInterrupt) { - mLaunchFullScreenIntentProvider.launchFullScreenIntent(entry) - } else if (fsiDecision.wouldInterruptWithoutDnd) { - // If DND was the only reason this entry was suppressed, note it for potential - // reconsideration on later ranking updates. - addForFSIReconsideration(entry, mSystemClock.currentTimeMillis()) - } - - // makeAndLogHeadsUpDecision includes check for whether this notification should be - // filtered - val shouldHeadsUpEver = - mVisualInterruptionDecisionProvider.makeAndLogHeadsUpDecision(entry).shouldInterrupt - mPostedEntries[entry.key] = PostedEntry( - entry, - wasAdded = true, - wasUpdated = false, - shouldHeadsUpEver = shouldHeadsUpEver, - shouldHeadsUpAgain = true, - isHeadsUpEntry = false, - isBinding = false, - ) + private val mNotifCollectionListener = + object : NotifCollectionListener { + /** + * Notification was just added and if it should heads up, bind the view and then show + * it. + */ + override fun onEntryAdded(entry: NotificationEntry) { + // First check whether this notification should launch a full screen intent, and + // launch it if needed. + val fsiDecision = + mVisualInterruptionDecisionProvider.makeUnloggedFullScreenIntentDecision(entry) + mVisualInterruptionDecisionProvider.logFullScreenIntentDecision(fsiDecision) + if (fsiDecision.shouldInterrupt) { + mLaunchFullScreenIntentProvider.launchFullScreenIntent(entry) + } else if (fsiDecision.wouldInterruptWithoutDnd) { + // If DND was the only reason this entry was suppressed, note it for potential + // reconsideration on later ranking updates. + addForFSIReconsideration(entry, mSystemClock.currentTimeMillis()) + } - // Record the last updated time for this key - setUpdateTime(entry, mSystemClock.currentTimeMillis()) - } + // makeAndLogHeadsUpDecision includes check for whether this notification should be + // filtered + val shouldHeadsUpEver = + mVisualInterruptionDecisionProvider + .makeAndLogHeadsUpDecision(entry) + .shouldInterrupt + mPostedEntries[entry.key] = + PostedEntry( + entry, + wasAdded = true, + wasUpdated = false, + shouldHeadsUpEver = shouldHeadsUpEver, + shouldHeadsUpAgain = true, + isHeadsUpEntry = false, + isBinding = false, + ) - /** - * Notification could've updated to be heads up or not heads up. Even if it did update to - * heads up, if the notification specified that it only wants to heads up once, don't heads - * up again. - */ - override fun onEntryUpdated(entry: NotificationEntry) { - val shouldHeadsUpEver = - mVisualInterruptionDecisionProvider.makeAndLogHeadsUpDecision(entry).shouldInterrupt - val shouldHeadsUpAgain = shouldHunAgain(entry) - val isHeadsUpEntry = mHeadsUpManager.isHeadsUpEntry(entry.key) - val isBinding = isEntryBinding(entry) - val posted = mPostedEntries.compute(entry.key) { _, value -> - value?.also { update -> - update.wasUpdated = true - update.shouldHeadsUpEver = shouldHeadsUpEver - update.shouldHeadsUpAgain = update.shouldHeadsUpAgain || shouldHeadsUpAgain - update.isHeadsUpEntry = isHeadsUpEntry - update.isBinding = isBinding - } ?: PostedEntry( - entry, - wasAdded = false, - wasUpdated = true, - shouldHeadsUpEver = shouldHeadsUpEver, - shouldHeadsUpAgain = shouldHeadsUpAgain, - isHeadsUpEntry = isHeadsUpEntry, - isBinding = isBinding, - ) + // Record the last updated time for this key + setUpdateTime(entry, mSystemClock.currentTimeMillis()) } - // Handle cancelling heads up here, rather than in the OnBeforeFinalizeFilter, so that - // work can be done before the ShadeListBuilder is run. This prevents re-entrant - // behavior between this Coordinator, HeadsUpManager, and VisualStabilityManager. - if (posted?.shouldHeadsUpEver == false) { - if (posted.isHeadsUpEntry) { - // We don't want this to be interrupting anymore, let's remove it - mHeadsUpManager.removeNotification(posted.key, false /*removeImmediately*/) - } else if (posted.isBinding) { - // Don't let the bind finish - cancelHeadsUpBind(posted.entry) + + /** + * Notification could've updated to be heads up or not heads up. Even if it did update + * to heads up, if the notification specified that it only wants to heads up once, don't + * heads up again. + */ + override fun onEntryUpdated(entry: NotificationEntry) { + val shouldHeadsUpEver = + mVisualInterruptionDecisionProvider + .makeAndLogHeadsUpDecision(entry) + .shouldInterrupt + val shouldHeadsUpAgain = shouldHunAgain(entry) + val isHeadsUpEntry = mHeadsUpManager.isHeadsUpEntry(entry.key) + val isBinding = isEntryBinding(entry) + val posted = + mPostedEntries.compute(entry.key) { _, value -> + value?.also { update -> + update.wasUpdated = true + update.shouldHeadsUpEver = shouldHeadsUpEver + update.shouldHeadsUpAgain = + update.shouldHeadsUpAgain || shouldHeadsUpAgain + update.isHeadsUpEntry = isHeadsUpEntry + update.isBinding = isBinding + } + ?: PostedEntry( + entry, + wasAdded = false, + wasUpdated = true, + shouldHeadsUpEver = shouldHeadsUpEver, + shouldHeadsUpAgain = shouldHeadsUpAgain, + isHeadsUpEntry = isHeadsUpEntry, + isBinding = isBinding, + ) + } + // Handle cancelling heads up here, rather than in the OnBeforeFinalizeFilter, so + // that + // work can be done before the ShadeListBuilder is run. This prevents re-entrant + // behavior between this Coordinator, HeadsUpManager, and VisualStabilityManager. + if (posted?.shouldHeadsUpEver == false) { + if (posted.isHeadsUpEntry) { + // We don't want this to be interrupting anymore, let's remove it + mHeadsUpManager.removeNotification(posted.key, false /*removeImmediately*/) + } else if (posted.isBinding) { + // Don't let the bind finish + cancelHeadsUpBind(posted.entry) + } } + + // Update last updated time for this entry + setUpdateTime(entry, mSystemClock.currentTimeMillis()) } - // Update last updated time for this entry - setUpdateTime(entry, mSystemClock.currentTimeMillis()) - } + /** Stop showing as heads up once removed from the notification collection */ + override fun onEntryRemoved(entry: NotificationEntry, reason: Int) { + mPostedEntries.remove(entry.key) + mEntriesUpdateTimes.remove(entry.key) + cancelHeadsUpBind(entry) + val entryKey = entry.key + if (mHeadsUpManager.isHeadsUpEntry(entryKey)) { + // TODO: This should probably know the RemoteInputCoordinator's conditions, + // or otherwise reference that coordinator's state, rather than replicate its + // logic + val removeImmediatelyForRemoteInput = + (mRemoteInputManager.isSpinning(entryKey) && + !NotificationRemoteInputManager.FORCE_REMOTE_INPUT_HISTORY) + mHeadsUpManager.removeNotification(entry.key, removeImmediatelyForRemoteInput) + } + } - /** - * Stop showing as heads up once removed from the notification collection - */ - override fun onEntryRemoved(entry: NotificationEntry, reason: Int) { - mPostedEntries.remove(entry.key) - mEntriesUpdateTimes.remove(entry.key) - cancelHeadsUpBind(entry) - val entryKey = entry.key - if (mHeadsUpManager.isHeadsUpEntry(entryKey)) { - // TODO: This should probably know the RemoteInputCoordinator's conditions, - // or otherwise reference that coordinator's state, rather than replicate its logic - val removeImmediatelyForRemoteInput = (mRemoteInputManager.isSpinning(entryKey) && - !NotificationRemoteInputManager.FORCE_REMOTE_INPUT_HISTORY) - mHeadsUpManager.removeNotification(entry.key, removeImmediatelyForRemoteInput) + override fun onEntryCleanUp(entry: NotificationEntry) { + mHeadsUpViewBinder.abortBindCallback(entry) } - } - override fun onEntryCleanUp(entry: NotificationEntry) { - mHeadsUpViewBinder.abortBindCallback(entry) - } + /** + * Identify notifications whose heads-up state changes when the notification rankings + * are updated, and have those changed notifications heads up if necessary. + * + * This method will occur after any operations in onEntryAdded or onEntryUpdated, so any + * handling of ranking changes needs to take into account that we may have just made a + * PostedEntry for some of these notifications. + */ + override fun onRankingApplied() { + // Because a ranking update may cause some notifications that are no longer (or were + // never) in mPostedEntries to need to heads up, we need to check every notification + // known to the pipeline. + for (entry in mNotifPipeline.allNotifs) { + // Only consider entries that are recent enough, since we want to apply a fairly + // strict threshold for when an entry should be updated via only ranking and not + // an + // app-provided notification update. + if (!isNewEnoughForRankingUpdate(entry)) continue + + // The only entries we consider heads up for here are entries that have never + // interrupted and that now say they should heads up or FSI; if they've heads + // uped in + // the past, we don't want to incorrectly heads up a second time if there wasn't + // an + // explicit notification update. + if (entry.hasInterrupted()) continue + + // Before potentially allowing heads-up, check for any candidates for a FSI + // launch. + // Any entry that is a candidate meets two criteria: + // - was suppressed from FSI launch only by a DND suppression + // - is within the recency window for reconsideration + // If any of these entries are no longer suppressed, launch the FSI now. + if (isCandidateForFSIReconsideration(entry)) { + val decision = + mVisualInterruptionDecisionProvider + .makeUnloggedFullScreenIntentDecision(entry) + if (decision.shouldInterrupt) { + // Log both the launch of the full screen and also that this was via a + // ranking update, and finally revoke candidacy for FSI reconsideration + mLogger.logEntryUpdatedToFullScreen(entry.key, decision.logReason) + mVisualInterruptionDecisionProvider.logFullScreenIntentDecision( + decision + ) + mLaunchFullScreenIntentProvider.launchFullScreenIntent(entry) + mFSIUpdateCandidates.remove(entry.key) + + // if we launch the FSI then this is no longer a candidate for HUN + continue + } else if (decision.wouldInterruptWithoutDnd) { + // decision has not changed; no need to log + } else { + // some other condition is now blocking FSI; log that and revoke + // candidacy + // for FSI reconsideration + mLogger.logEntryDisqualifiedFromFullScreen( + entry.key, + decision.logReason + ) + mVisualInterruptionDecisionProvider.logFullScreenIntentDecision( + decision + ) + mFSIUpdateCandidates.remove(entry.key) + } + } - /** - * Identify notifications whose heads-up state changes when the notification rankings are - * updated, and have those changed notifications heads up if necessary. - * - * This method will occur after any operations in onEntryAdded or onEntryUpdated, so any - * handling of ranking changes needs to take into account that we may have just made a - * PostedEntry for some of these notifications. - */ - override fun onRankingApplied() { - // Because a ranking update may cause some notifications that are no longer (or were - // never) in mPostedEntries to need to heads up, we need to check every notification - // known to the pipeline. - for (entry in mNotifPipeline.allNotifs) { - // Only consider entries that are recent enough, since we want to apply a fairly - // strict threshold for when an entry should be updated via only ranking and not an - // app-provided notification update. - if (!isNewEnoughForRankingUpdate(entry)) continue - - // The only entries we consider heads up for here are entries that have never - // interrupted and that now say they should heads up or FSI; if they've heads uped in - // the past, we don't want to incorrectly heads up a second time if there wasn't an - // explicit notification update. - if (entry.hasInterrupted()) continue - - // Before potentially allowing heads-up, check for any candidates for a FSI launch. - // Any entry that is a candidate meets two criteria: - // - was suppressed from FSI launch only by a DND suppression - // - is within the recency window for reconsideration - // If any of these entries are no longer suppressed, launch the FSI now. - if (isCandidateForFSIReconsideration(entry)) { + // The cases where we should consider this notification to be updated: + // - if this entry is not present in PostedEntries, and is now in a + // shouldHeadsUp + // state + // - if it is present in PostedEntries and the previous state of shouldHeadsUp + // differs from the updated one val decision = - mVisualInterruptionDecisionProvider.makeUnloggedFullScreenIntentDecision( - entry + mVisualInterruptionDecisionProvider.makeUnloggedHeadsUpDecision(entry) + val shouldHeadsUpEver = decision.shouldInterrupt + val postedShouldHeadsUpEver = + mPostedEntries[entry.key]?.shouldHeadsUpEver ?: false + val shouldUpdateEntry = postedShouldHeadsUpEver != shouldHeadsUpEver + + if (shouldUpdateEntry) { + mLogger.logEntryUpdatedByRanking( + entry.key, + shouldHeadsUpEver, + decision.logReason ) - if (decision.shouldInterrupt) { - // Log both the launch of the full screen and also that this was via a - // ranking update, and finally revoke candidacy for FSI reconsideration - mLogger.logEntryUpdatedToFullScreen(entry.key, decision.logReason) - mVisualInterruptionDecisionProvider.logFullScreenIntentDecision(decision) - mLaunchFullScreenIntentProvider.launchFullScreenIntent(entry) - mFSIUpdateCandidates.remove(entry.key) - - // if we launch the FSI then this is no longer a candidate for HUN - continue - } else if (decision.wouldInterruptWithoutDnd) { - // decision has not changed; no need to log - } else { - // some other condition is now blocking FSI; log that and revoke candidacy - // for FSI reconsideration - mLogger.logEntryDisqualifiedFromFullScreen(entry.key, decision.logReason) - mVisualInterruptionDecisionProvider.logFullScreenIntentDecision(decision) - mFSIUpdateCandidates.remove(entry.key) + onEntryUpdated(entry) } } - - // The cases where we should consider this notification to be updated: - // - if this entry is not present in PostedEntries, and is now in a shouldHeadsUp - // state - // - if it is present in PostedEntries and the previous state of shouldHeadsUp - // differs from the updated one - val decision = - mVisualInterruptionDecisionProvider.makeUnloggedHeadsUpDecision(entry) - val shouldHeadsUpEver = decision.shouldInterrupt - val postedShouldHeadsUpEver = mPostedEntries[entry.key]?.shouldHeadsUpEver ?: false - val shouldUpdateEntry = postedShouldHeadsUpEver != shouldHeadsUpEver - - if (shouldUpdateEntry) { - mLogger.logEntryUpdatedByRanking( - entry.key, - shouldHeadsUpEver, - decision.logReason - ) - onEntryUpdated(entry) - } } } - } - /** - * Checks whether an update for a notification warrants an heads up for the user. - */ + /** Checks whether an update for a notification warrants an heads up for the user. */ private fun shouldHunAgain(entry: NotificationEntry): Boolean { return (!entry.hasInterrupted() || - (entry.sbn.notification.flags and Notification.FLAG_ONLY_ALERT_ONCE) == 0) + (entry.sbn.notification.flags and Notification.FLAG_ONLY_ALERT_ONCE) == 0) } - /** - * Sets the updated time for the given entry to the specified time. - */ + /** Sets the updated time for the given entry to the specified time. */ @VisibleForTesting fun setUpdateTime(entry: NotificationEntry, time: Long) { mEntriesUpdateTimes[entry.key] = time @@ -593,10 +641,10 @@ class HeadsUpCoordinator @Inject constructor( } /** - * Checks whether the entry is new enough to be updated via ranking update. - * We want to avoid updating an entry too long after it was originally posted/updated when we're - * only reacting to a ranking change, as relevant ranking updates are expected to come in - * fairly soon after the posting of a notification. + * Checks whether the entry is new enough to be updated via ranking update. We want to avoid + * updating an entry too long after it was originally posted/updated when we're only reacting to + * a ranking change, as relevant ranking updates are expected to come in fairly soon after the + * posting of a notification. */ private fun isNewEnoughForRankingUpdate(entry: NotificationEntry): Boolean { // If we don't have an update time for this key, default to "too old" @@ -648,72 +696,92 @@ class HeadsUpCoordinator @Inject constructor( * @see HeadsUpManager.setUserActionMayIndirectlyRemove * @see HeadsUpManager.canRemoveImmediately */ - private val mActionPressListener = Consumer<NotificationEntry> { entry -> - mHeadsUpManager.setUserActionMayIndirectlyRemove(entry) - mExecutor.execute { endNotifLifetimeExtensionIfExtended(entry) } - } - - private val mLifetimeExtender = object : NotifLifetimeExtender { - override fun getName() = TAG - - override fun setCallback(callback: OnEndLifetimeExtensionCallback) { - mEndLifetimeExtension = callback + private val mActionPressListener = + Consumer<NotificationEntry> { entry -> + mHeadsUpManager.setUserActionMayIndirectlyRemove(entry) + mExecutor.execute { endNotifLifetimeExtensionIfExtended(entry) } } - override fun maybeExtendLifetime(entry: NotificationEntry, reason: Int): Boolean { - if (mHeadsUpManager.canRemoveImmediately(entry.key)) { - return false + private val mLifetimeExtender = + object : NotifLifetimeExtender { + override fun getName() = TAG + + override fun setCallback(callback: OnEndLifetimeExtensionCallback) { + mEndLifetimeExtension = callback } - if (isSticky(entry)) { - val removeAfterMillis = mHeadsUpManager.getEarliestRemovalTime(entry.key) - mNotifsExtendingLifetime[entry] = mExecutor.executeDelayed({ - mHeadsUpManager.removeNotification(entry.key, /* releaseImmediately */ true) - }, removeAfterMillis) - } else { - mExecutor.execute { - mHeadsUpManager.removeNotification(entry.key, /* releaseImmediately */ false) + + override fun maybeExtendLifetime(entry: NotificationEntry, reason: Int): Boolean { + if (mHeadsUpManager.canRemoveImmediately(entry.key)) { + return false + } + if (isSticky(entry)) { + val removeAfterMillis = mHeadsUpManager.getEarliestRemovalTime(entry.key) + mNotifsExtendingLifetime[entry] = + mExecutor.executeDelayed( + { + mHeadsUpManager.removeNotification( + entry.key, /* releaseImmediately */ + true + ) + }, + removeAfterMillis + ) + } else { + mExecutor.execute { + mHeadsUpManager.removeNotification( + entry.key, /* releaseImmediately */ + false + ) + } + mNotifsExtendingLifetime[entry] = null } - mNotifsExtendingLifetime[entry] = null + return true } - return true - } - override fun cancelLifetimeExtension(entry: NotificationEntry) { - mNotifsExtendingLifetime.remove(entry)?.run() + override fun cancelLifetimeExtension(entry: NotificationEntry) { + mNotifsExtendingLifetime.remove(entry)?.run() + } } - } - private val mNotifPromoter = object : NotifPromoter(TAG) { - override fun shouldPromoteToTopLevel(entry: NotificationEntry): Boolean = - isGoingToShowHunNoRetract(entry) - } + private val mNotifPromoter = + object : NotifPromoter(TAG) { + override fun shouldPromoteToTopLevel(entry: NotificationEntry): Boolean = + isGoingToShowHunNoRetract(entry) + } - val sectioner = object : NotifSectioner("HeadsUp", BUCKET_HEADS_UP) { - override fun isInSection(entry: ListEntry): Boolean = - // TODO: This check won't notice if a child of the group is going to HUN... - isGoingToShowHunNoRetract(entry) + val sectioner = + object : NotifSectioner("HeadsUp", BUCKET_HEADS_UP) { + override fun isInSection(entry: ListEntry): Boolean = + // TODO: This check won't notice if a child of the group is going to HUN... + isGoingToShowHunNoRetract(entry) - override fun getComparator(): NotifComparator { - return object : NotifComparator("HeadsUp") { - override fun compare(o1: ListEntry, o2: ListEntry): Int = - mHeadsUpManager.compare(o1.representativeEntry, o2.representativeEntry) + override fun getComparator(): NotifComparator { + return object : NotifComparator("HeadsUp") { + override fun compare(o1: ListEntry, o2: ListEntry): Int = + mHeadsUpManager.compare(o1.representativeEntry, o2.representativeEntry) + } } + + override fun getHeaderNodeController(): NodeController? = + // TODO: remove SHOW_ALL_SECTIONS, this redundant method, and + // mIncomingHeaderController + if (RankingCoordinator.SHOW_ALL_SECTIONS) mIncomingHeaderController else null } - override fun getHeaderNodeController(): NodeController? = - // TODO: remove SHOW_ALL_SECTIONS, this redundant method, and mIncomingHeaderController - if (RankingCoordinator.SHOW_ALL_SECTIONS) mIncomingHeaderController else null - } + private val mOnHeadsUpChangedListener = + object : OnHeadsUpChangedListener { + override fun onHeadsUpStateChanged(entry: NotificationEntry, isHeadsUp: Boolean) { + if (!isHeadsUp) { + mNotifPromoter.invalidateList("headsUpEnded: ${entry.logKey}") + mHeadsUpViewBinder.unbindHeadsUpView(entry) + endNotifLifetimeExtensionIfExtended(entry) + } + } - private val mOnHeadsUpChangedListener = object : OnHeadsUpChangedListener { - override fun onHeadsUpStateChanged(entry: NotificationEntry, isHeadsUp: Boolean) { - if (!isHeadsUp) { - mNotifPromoter.invalidateList("headsUpEnded: ${entry.logKey}") - mHeadsUpViewBinder.unbindHeadsUpView(entry) - endNotifLifetimeExtensionIfExtended(entry) + override fun onHeadsUpAnimatingAwayEnded(entry: NotificationEntry) { + mNotifPromoter.invalidateList("headsUpAnimatingAwayEnded: ${entry.logKey}") } } - } private fun isSticky(entry: NotificationEntry) = mHeadsUpManager.isSticky(entry.key) @@ -726,8 +794,9 @@ class HeadsUpCoordinator @Inject constructor( * Whether the notification is already heads up or binding so that it can imminently heads up */ private fun isAttemptingToShowHun(entry: ListEntry) = - mHeadsUpManager.isHeadsUpEntry(entry.key) || isEntryBinding(entry) - || isHeadsUpAnimatingAway(entry) + mHeadsUpManager.isHeadsUpEntry(entry.key) || + isEntryBinding(entry) || + isHeadsUpAnimatingAway(entry) private fun isHeadsUpAnimatingAway(entry: ListEntry): Boolean { if (!GroupHunAnimationFix.isEnabled) return false @@ -735,19 +804,19 @@ class HeadsUpCoordinator @Inject constructor( } /** - * Whether the notification is already heads up/binding per [isAttemptingToShowHun] OR if it - * has been updated so that it should heads up this update. This method is permissive because - * it returns `true` even if the update would (in isolation of its group) cause the heads up to - * be retracted. This is important for not retracting transferred group heads ups. + * Whether the notification is already heads up/binding per [isAttemptingToShowHun] OR if it has + * been updated so that it should heads up this update. This method is permissive because it + * returns `true` even if the update would (in isolation of its group) cause the heads up to be + * retracted. This is important for not retracting transferred group heads ups. */ private fun isGoingToShowHunNoRetract(entry: ListEntry) = mPostedEntries[entry.key]?.calculateShouldBeHeadsUpNoRetract ?: isAttemptingToShowHun(entry) /** * If the notification has been updated, then whether it should HUN in isolation, otherwise - * defers to the already heads up/binding state of [isAttemptingToShowHun]. This method is - * strict because any update which would revoke the heads up supersedes the current - * heads up/binding state. + * defers to the already heads up/binding state of [isAttemptingToShowHun]. This method is + * strict because any update which would revoke the heads up supersedes the current heads + * up/binding state. */ private fun isGoingToShowHunStrict(entry: ListEntry) = mPostedEntries[entry.key]?.calculateShouldBeHeadsUpStrict ?: isAttemptingToShowHun(entry) @@ -779,14 +848,21 @@ class HeadsUpCoordinator @Inject constructor( val key = entry.key val isHeadsUpAlready: Boolean get() = isHeadsUpEntry || isBinding + val calculateShouldBeHeadsUpStrict: Boolean get() = shouldHeadsUpEver && (wasAdded || shouldHeadsUpAgain || isHeadsUpAlready) + val calculateShouldBeHeadsUpNoRetract: Boolean get() = isHeadsUpAlready || (shouldHeadsUpEver && (wasAdded || shouldHeadsUpAgain)) } } -private enum class GroupLocation { Detached, Isolated, Summary, Child } +private enum class GroupLocation { + Detached, + Isolated, + Summary, + Child +} private fun Map<String, GroupLocation>.getLocation(key: String): GroupLocation = getOrDefault(key, GroupLocation.Detached) @@ -804,6 +880,7 @@ private fun <R> HeadsUpManager.modifyHuns(block: (HunMutator) -> R): R { /** Mutates the HeadsUp state of notifications. */ private interface HunMutator { fun updateNotification(key: String, shouldHeadsUpAgain: Boolean) + fun removeNotification(key: String, releaseImmediately: Boolean) } diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/coordinator/SensitiveContentCoordinator.kt b/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/coordinator/SensitiveContentCoordinator.kt index ac2a0d898081..1e0e597ad3e8 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/coordinator/SensitiveContentCoordinator.kt +++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/coordinator/SensitiveContentCoordinator.kt @@ -20,10 +20,14 @@ import android.app.Notification import android.os.UserHandle import com.android.keyguard.KeyguardUpdateMonitor import com.android.server.notification.Flags.screenshareNotificationHiding +import com.android.systemui.dagger.qualifiers.Application +import com.android.systemui.deviceentry.domain.interactor.DeviceEntryInteractor import com.android.systemui.plugins.statusbar.StatusBarStateController +import com.android.systemui.scene.domain.interactor.SceneInteractor +import com.android.systemui.scene.shared.flag.SceneContainerFlag +import com.android.systemui.scene.shared.model.Scenes import com.android.systemui.statusbar.NotificationLockscreenUserManager import com.android.systemui.statusbar.StatusBarState -import com.android.systemui.statusbar.notification.collection.listbuilder.pluggable.NotifFilter import com.android.systemui.statusbar.notification.DynamicPrivacyController import com.android.systemui.statusbar.notification.collection.GroupEntry import com.android.systemui.statusbar.notification.collection.ListEntry @@ -32,27 +36,33 @@ import com.android.systemui.statusbar.notification.collection.NotificationEntry import com.android.systemui.statusbar.notification.collection.coordinator.dagger.CoordinatorScope import com.android.systemui.statusbar.notification.collection.listbuilder.OnBeforeRenderListListener import com.android.systemui.statusbar.notification.collection.listbuilder.pluggable.Invalidator +import com.android.systemui.statusbar.notification.collection.listbuilder.pluggable.NotifFilter import com.android.systemui.statusbar.policy.KeyguardStateController import com.android.systemui.statusbar.policy.SensitiveNotificationProtectionController import com.android.systemui.user.domain.interactor.SelectedUserInteractor import dagger.Binds import dagger.Module import javax.inject.Inject +import kotlinx.coroutines.CoroutineScope +import kotlinx.coroutines.flow.distinctUntilChanged +import kotlinx.coroutines.flow.mapNotNull +import kotlinx.coroutines.launch @Module(includes = [PrivateSensitiveContentCoordinatorModule::class]) interface SensitiveContentCoordinatorModule @Module interface PrivateSensitiveContentCoordinatorModule { - @Binds - fun bindCoordinator(impl: SensitiveContentCoordinatorImpl): SensitiveContentCoordinator + @Binds fun bindCoordinator(impl: SensitiveContentCoordinatorImpl): SensitiveContentCoordinator } /** Coordinates re-inflation and post-processing of sensitive notification content. */ interface SensitiveContentCoordinator : Coordinator @CoordinatorScope -class SensitiveContentCoordinatorImpl @Inject constructor( +class SensitiveContentCoordinatorImpl +@Inject +constructor( private val dynamicPrivacyController: DynamicPrivacyController, private val lockscreenUserManager: NotificationLockscreenUserManager, private val keyguardUpdateMonitor: KeyguardUpdateMonitor, @@ -61,45 +71,85 @@ class SensitiveContentCoordinatorImpl @Inject constructor( private val selectedUserInteractor: SelectedUserInteractor, private val sensitiveNotificationProtectionController: SensitiveNotificationProtectionController, -) : Invalidator("SensitiveContentInvalidator"), - SensitiveContentCoordinator, - DynamicPrivacyController.Listener, - OnBeforeRenderListListener { - private val onSensitiveStateChanged = Runnable() { - invalidateList("onSensitiveStateChanged") - } - - private val screenshareSecretFilter = object : NotifFilter("ScreenshareSecretFilter") { - val NotificationEntry.isSecret - get() = channel?.lockscreenVisibility == Notification.VISIBILITY_SECRET || - sbn.notification?.visibility == Notification.VISIBILITY_SECRET - override fun shouldFilterOut(entry: NotificationEntry, now: Long): Boolean { - return screenshareNotificationHiding() && - sensitiveNotificationProtectionController.isSensitiveStateActive && - entry.isSecret + private val deviceEntryInteractor: DeviceEntryInteractor, + private val sceneInteractor: SceneInteractor, + @Application private val scope: CoroutineScope, +) : + Invalidator("SensitiveContentInvalidator"), + SensitiveContentCoordinator, + DynamicPrivacyController.Listener, + OnBeforeRenderListListener { + private var inTransitionFromLockedToGone = false + + private val onSensitiveStateChanged = Runnable() { invalidateList("onSensitiveStateChanged") } + + private val screenshareSecretFilter = + object : NotifFilter("ScreenshareSecretFilter") { + val NotificationEntry.isSecret + get() = + channel?.lockscreenVisibility == Notification.VISIBILITY_SECRET || + sbn.notification?.visibility == Notification.VISIBILITY_SECRET + + override fun shouldFilterOut(entry: NotificationEntry, now: Long): Boolean { + return screenshareNotificationHiding() && + sensitiveNotificationProtectionController.isSensitiveStateActive && + entry.isSecret + } } - } override fun attach(pipeline: NotifPipeline) { dynamicPrivacyController.addListener(this) if (screenshareNotificationHiding()) { - sensitiveNotificationProtectionController - .registerSensitiveStateListener(onSensitiveStateChanged) + sensitiveNotificationProtectionController.registerSensitiveStateListener( + onSensitiveStateChanged + ) } pipeline.addOnBeforeRenderListListener(this) pipeline.addPreRenderInvalidator(this) if (screenshareNotificationHiding()) { pipeline.addFinalizeFilter(screenshareSecretFilter) } + + if (SceneContainerFlag.isEnabled) { + scope.launch { + sceneInteractor.transitionState + .mapNotNull { + val transitioningToGone = it.isTransitioning(to = Scenes.Gone) + val deviceEntered = deviceEntryInteractor.isDeviceEntered.value + when { + transitioningToGone && !deviceEntered -> true + !transitioningToGone -> false + else -> null + } + } + .distinctUntilChanged() + .collect { + inTransitionFromLockedToGone = it + invalidateList("inTransitionFromLockedToGoneChanged") + } + } + } } override fun onDynamicPrivacyChanged(): Unit = invalidateList("onDynamicPrivacyChanged") + private val isKeyguardGoingAway: Boolean + get() { + if (SceneContainerFlag.isEnabled) { + return inTransitionFromLockedToGone + } else { + return keyguardStateController.isKeyguardGoingAway + } + } + override fun onBeforeRenderList(entries: List<ListEntry>) { - if (keyguardStateController.isKeyguardGoingAway || + if ( + isKeyguardGoingAway || statusBarStateController.state == StatusBarState.KEYGUARD && - keyguardUpdateMonitor.getUserUnlockedWithBiometricAndIsBypassing( - selectedUserInteractor.getSelectedUserId())) { + keyguardUpdateMonitor.getUserUnlockedWithBiometricAndIsBypassing( + selectedUserInteractor.getSelectedUserId() + ) + ) { // don't update yet if: // - the keyguard is currently going away // - LS is about to be dismissed by a biometric that bypasses LS (avoid notif flash) @@ -109,35 +159,40 @@ class SensitiveContentCoordinatorImpl @Inject constructor( return } - val isSensitiveContentProtectionActive = screenshareNotificationHiding() && - sensitiveNotificationProtectionController.isSensitiveStateActive + val isSensitiveContentProtectionActive = + screenshareNotificationHiding() && + sensitiveNotificationProtectionController.isSensitiveStateActive val currentUserId = lockscreenUserManager.currentUserId val devicePublic = lockscreenUserManager.isLockscreenPublicMode(currentUserId) - val deviceSensitive = (devicePublic && + val deviceSensitive = + (devicePublic && !lockscreenUserManager.userAllowsPrivateNotificationsInPublic(currentUserId)) || isSensitiveContentProtectionActive val dynamicallyUnlocked = dynamicPrivacyController.isDynamicallyUnlocked for (entry in extractAllRepresentativeEntries(entries).filter { it.rowExists() }) { val notifUserId = entry.sbn.user.identifier - val userLockscreen = devicePublic || - lockscreenUserManager.isLockscreenPublicMode(notifUserId) - val userPublic = when { - // if we're not on the lockscreen, we're definitely private - !userLockscreen -> false - // we are on the lockscreen, so unless we're dynamically unlocked, we're - // definitely public - !dynamicallyUnlocked -> true - // we're dynamically unlocked, but check if the notification needs - // a separate challenge if it's from a work profile - else -> when (notifUserId) { - currentUserId -> false - UserHandle.USER_ALL -> false - else -> lockscreenUserManager.needsSeparateWorkChallenge(notifUserId) + val userLockscreen = + devicePublic || lockscreenUserManager.isLockscreenPublicMode(notifUserId) + val userPublic = + when { + // if we're not on the lockscreen, we're definitely private + !userLockscreen -> false + // we are on the lockscreen, so unless we're dynamically unlocked, we're + // definitely public + !dynamicallyUnlocked -> true + // we're dynamically unlocked, but check if the notification needs + // a separate challenge if it's from a work profile + else -> + when (notifUserId) { + currentUserId -> false + UserHandle.USER_ALL -> false + else -> lockscreenUserManager.needsSeparateWorkChallenge(notifUserId) + } } - } - val shouldProtectNotification = screenshareNotificationHiding() && - sensitiveNotificationProtectionController.shouldProtectNotification(entry) + val shouldProtectNotification = + screenshareNotificationHiding() && + sensitiveNotificationProtectionController.shouldProtectNotification(entry) val needsRedaction = lockscreenUserManager.needsRedaction(entry) val isSensitive = userPublic && needsRedaction @@ -149,9 +204,7 @@ class SensitiveContentCoordinatorImpl @Inject constructor( } } -private fun extractAllRepresentativeEntries( - entries: List<ListEntry> -): Sequence<NotificationEntry> = +private fun extractAllRepresentativeEntries(entries: List<ListEntry>): Sequence<NotificationEntry> = entries.asSequence().flatMap(::extractAllRepresentativeEntries) private fun extractAllRepresentativeEntries(listEntry: ListEntry): Sequence<NotificationEntry> = diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/data/NotificationSettingsRepositoryModule.kt b/packages/SystemUI/src/com/android/systemui/statusbar/notification/data/NotificationSettingsRepositoryModule.kt index a7970c70e4ed..af21e75da37e 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/data/NotificationSettingsRepositoryModule.kt +++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/data/NotificationSettingsRepositoryModule.kt @@ -19,14 +19,16 @@ package com.android.systemui.statusbar.notification.data import com.android.systemui.dagger.SysUISingleton import com.android.systemui.dagger.qualifiers.Background import com.android.systemui.settings.SecureSettingsRepositoryModule +import com.android.systemui.settings.SystemSettingsRepositoryModule import com.android.systemui.shared.notifications.data.repository.NotificationSettingsRepository import com.android.systemui.shared.settings.data.repository.SecureSettingsRepository +import com.android.systemui.shared.settings.data.repository.SystemSettingsRepository import dagger.Module import dagger.Provides import kotlinx.coroutines.CoroutineDispatcher import kotlinx.coroutines.CoroutineScope -@Module(includes = [SecureSettingsRepositoryModule::class]) +@Module(includes = [SecureSettingsRepositoryModule::class, SystemSettingsRepositoryModule::class]) object NotificationSettingsRepositoryModule { @Provides @SysUISingleton @@ -34,10 +36,12 @@ object NotificationSettingsRepositoryModule { @Background backgroundScope: CoroutineScope, @Background backgroundDispatcher: CoroutineDispatcher, secureSettingsRepository: SecureSettingsRepository, + systemSettingsRepository: SystemSettingsRepository, ): NotificationSettingsRepository = NotificationSettingsRepository( backgroundScope, backgroundDispatcher, - secureSettingsRepository + secureSettingsRepository, + systemSettingsRepository ) } diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/domain/interactor/SeenNotificationsInteractor.kt b/packages/SystemUI/src/com/android/systemui/statusbar/notification/domain/interactor/SeenNotificationsInteractor.kt index 90a05ef99586..29564326481f 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/domain/interactor/SeenNotificationsInteractor.kt +++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/domain/interactor/SeenNotificationsInteractor.kt @@ -109,7 +109,7 @@ constructor( .map { secureSettings.getIntForUser( name = Settings.Secure.LOCK_SCREEN_SHOW_ONLY_UNSEEN_NOTIFICATIONS, - def = 0, + default = 0, userHandle = UserHandle.USER_CURRENT, ) == 1 } diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/interruption/CommonVisualInterruptionSuppressors.kt b/packages/SystemUI/src/com/android/systemui/statusbar/notification/interruption/CommonVisualInterruptionSuppressors.kt index 9d09595d2c23..a6ca3ab8bce3 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/interruption/CommonVisualInterruptionSuppressors.kt +++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/interruption/CommonVisualInterruptionSuppressors.kt @@ -46,6 +46,7 @@ import com.android.internal.messages.nano.SystemMessageProto.SystemMessage import com.android.systemui.dagger.qualifiers.Main import com.android.systemui.plugins.statusbar.StatusBarStateController import com.android.systemui.settings.UserTracker +import com.android.systemui.shared.notifications.domain.interactor.NotificationSettingsInteractor import com.android.systemui.statusbar.StatusBarState.SHADE import com.android.systemui.statusbar.notification.collection.NotificationEntry import com.android.systemui.statusbar.notification.interruption.NotificationInterruptStateProviderImpl.MAX_HUN_WHEN_AGE_MS @@ -57,7 +58,6 @@ import com.android.systemui.statusbar.policy.BatteryController import com.android.systemui.statusbar.policy.HeadsUpManager import com.android.systemui.util.NotificationChannels import com.android.systemui.util.settings.GlobalSettings -import com.android.systemui.util.settings.SystemSettings import com.android.systemui.util.time.SystemClock import com.android.wm.shell.bubbles.Bubbles import java.util.Optional @@ -148,12 +148,12 @@ class PeekAlreadyBubbledSuppressor( } } -class PeekDndSuppressor() : +class PeekDndSuppressor : VisualInterruptionFilter(types = setOf(PEEK), reason = "suppressed by DND") { override fun shouldSuppress(entry: NotificationEntry) = entry.shouldSuppressPeek() } -class PeekNotImportantSuppressor() : +class PeekNotImportantSuppressor : VisualInterruptionFilter(types = setOf(PEEK), reason = "importance < HIGH") { override fun shouldSuppress(entry: NotificationEntry) = entry.importance < IMPORTANCE_HIGH } @@ -194,12 +194,12 @@ class PeekOldWhenSuppressor(private val systemClock: SystemClock) : } } -class PulseEffectSuppressor() : +class PulseEffectSuppressor : VisualInterruptionFilter(types = setOf(PULSE), reason = "suppressed by DND") { override fun shouldSuppress(entry: NotificationEntry) = entry.shouldSuppressAmbient() } -class PulseLockscreenVisibilityPrivateSuppressor() : +class PulseLockscreenVisibilityPrivateSuppressor : VisualInterruptionFilter( types = setOf(PULSE), reason = "hidden by lockscreen visibility override" @@ -208,12 +208,12 @@ class PulseLockscreenVisibilityPrivateSuppressor() : entry.ranking.lockscreenVisibilityOverride == VISIBILITY_PRIVATE } -class PulseLowImportanceSuppressor() : +class PulseLowImportanceSuppressor : VisualInterruptionFilter(types = setOf(PULSE), reason = "importance < DEFAULT") { override fun shouldSuppress(entry: NotificationEntry) = entry.importance < IMPORTANCE_DEFAULT } -class HunGroupAlertBehaviorSuppressor() : +class HunGroupAlertBehaviorSuppressor : VisualInterruptionFilter( types = setOf(PEEK, PULSE), reason = "suppressive group alert behavior" @@ -222,26 +222,23 @@ class HunGroupAlertBehaviorSuppressor() : entry.sbn.let { it.isGroup && it.notification.suppressAlertingDueToGrouping() } } -class HunSilentNotificationSuppressor() : - VisualInterruptionFilter( - types = setOf(PEEK, PULSE), - reason = "notification isSilent" - ) { +class HunSilentNotificationSuppressor : + VisualInterruptionFilter(types = setOf(PEEK, PULSE), reason = "notification isSilent") { override fun shouldSuppress(entry: NotificationEntry) = entry.sbn.let { Flags.notificationSilentFlag() && it.notification.isSilent } } -class HunJustLaunchedFsiSuppressor() : +class HunJustLaunchedFsiSuppressor : VisualInterruptionFilter(types = setOf(PEEK, PULSE), reason = "just launched FSI") { override fun shouldSuppress(entry: NotificationEntry) = entry.hasJustLaunchedFullScreenIntent() } -class BubbleNotAllowedSuppressor() : - VisualInterruptionFilter(types = setOf(BUBBLE), reason = "cannot bubble") { +class BubbleNotAllowedSuppressor : + VisualInterruptionFilter(types = setOf(BUBBLE), reason = "cannot bubble", isSpammy = true) { override fun shouldSuppress(entry: NotificationEntry) = !entry.canBubble() } -class BubbleNoMetadataSuppressor() : +class BubbleNoMetadataSuppressor : VisualInterruptionFilter(types = setOf(BUBBLE), reason = "has no or invalid bubble metadata") { private fun isValidMetadata(metadata: BubbleMetadata?) = @@ -264,6 +261,7 @@ class AlertKeyguardVisibilitySuppressor( /** * Set with: + * * adb shell setprop persist.force_show_avalanche_edu_once 1 && adb shell stop; adb shell start */ private const val FORCE_SHOW_AVALANCHE_EDU_ONCE = "persist.force_show_avalanche_edu_once" @@ -273,7 +271,7 @@ private const val PREF_HAS_SEEN_AVALANCHE_EDU = "has_seen_avalanche_edu" class AvalancheSuppressor( private val avalancheProvider: AvalancheProvider, private val systemClock: SystemClock, - private val systemSettings: SystemSettings, + private val settingsInteractor: NotificationSettingsInteractor, private val packageManager: PackageManager, private val uiEventLogger: UiEventLogger, private val context: Context, @@ -298,7 +296,7 @@ class AvalancheSuppressor( // education HUNs. private var hasShownOnceForDebug = false - private fun shouldShowEdu() : Boolean { + private fun shouldShowEdu(): Boolean { val forceShowOnce = SystemProperties.get(FORCE_SHOW_AVALANCHE_EDU_ONCE, "").equals("1") return !hasSeenEdu || (forceShowOnce && !hasShownOnceForDebug) } @@ -361,28 +359,26 @@ class AvalancheSuppressor( return true } - /** - * Show avalanche education HUN from SystemUI. - */ + /** Show avalanche education HUN from SystemUI. */ private fun showEdu() { val res = context.resources - val titleStr = res.getString( - com.android.systemui.res.R.string.adaptive_notification_edu_hun_title) - val textStr = res.getString( - com.android.systemui.res.R.string.adaptive_notification_edu_hun_text) - val actionStr = res.getString( - com.android.systemui.res.R.string.go_to_adaptive_notification_settings) + val titleStr = + res.getString(com.android.systemui.res.R.string.adaptive_notification_edu_hun_title) + val textStr = + res.getString(com.android.systemui.res.R.string.adaptive_notification_edu_hun_text) + val actionStr = + res.getString(com.android.systemui.res.R.string.go_to_adaptive_notification_settings) val intent = Intent(Settings.ACTION_MANAGE_ADAPTIVE_NOTIFICATIONS) - val pendingIntent = PendingIntent.getActivity( - context, 0, intent, - PendingIntent.FLAG_IMMUTABLE - ) + val pendingIntent = + PendingIntent.getActivity(context, 0, intent, PendingIntent.FLAG_IMMUTABLE) // Replace "System UI" app name with "Android System" val bundle = Bundle() - bundle.putString(Notification.EXTRA_SUBSTITUTE_APP_NAME, - context.getString(com.android.internal.R.string.android_system_label)) + bundle.putString( + Notification.EXTRA_SUBSTITUTE_APP_NAME, + context.getString(com.android.internal.R.string.android_system_label) + ) val builder = Notification.Builder(context, NotificationChannels.ALERTS) @@ -400,7 +396,7 @@ class AvalancheSuppressor( notificationManager.notify(SystemMessage.NOTE_ADAPTIVE_NOTIFICATIONS, builder.build()) hasSeenEdu = true - hasShownOnceForDebug = true; + hasShownOnceForDebug = true } private fun calculateState(entry: NotificationEntry): State { @@ -452,7 +448,6 @@ class AvalancheSuppressor( } private fun isCooldownEnabled(): Boolean { - return systemSettings.getInt(Settings.System.NOTIFICATION_COOLDOWN_ENABLED, /* def */ 1) == - 1 + return settingsInteractor.isCooldownEnabled.value } } diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/interruption/VisualInterruptionDecisionLogger.kt b/packages/SystemUI/src/com/android/systemui/statusbar/notification/interruption/VisualInterruptionDecisionLogger.kt index 1470b0331359..c204ea9097de 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/interruption/VisualInterruptionDecisionLogger.kt +++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/interruption/VisualInterruptionDecisionLogger.kt @@ -16,6 +16,7 @@ package com.android.systemui.statusbar.notification.interruption +import android.util.Log import com.android.systemui.log.LogBuffer import com.android.systemui.log.core.LogLevel.DEBUG import com.android.systemui.log.core.LogLevel.INFO @@ -24,11 +25,15 @@ import com.android.systemui.log.dagger.NotificationInterruptLog import com.android.systemui.statusbar.notification.collection.NotificationEntry import com.android.systemui.statusbar.notification.interruption.VisualInterruptionDecisionProvider.FullScreenIntentDecision import com.android.systemui.statusbar.notification.logKey +import com.android.systemui.util.Compile import javax.inject.Inject class VisualInterruptionDecisionLogger @Inject constructor(@NotificationInterruptLog val buffer: LogBuffer) { + + val spew: Boolean = Compile.IS_DEBUG && Log.isLoggable(TAG, Log.VERBOSE) + fun logHeadsUpFeatureChanged(isEnabled: Boolean) { buffer.log( TAG, diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/interruption/VisualInterruptionDecisionProviderImpl.kt b/packages/SystemUI/src/com/android/systemui/statusbar/notification/interruption/VisualInterruptionDecisionProviderImpl.kt index 1c476ce0362b..8e8d9b69ac58 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/interruption/VisualInterruptionDecisionProviderImpl.kt +++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/interruption/VisualInterruptionDecisionProviderImpl.kt @@ -29,6 +29,7 @@ import com.android.internal.logging.UiEventLogger.UiEventEnum import com.android.systemui.dagger.qualifiers.Main import com.android.systemui.plugins.statusbar.StatusBarStateController import com.android.systemui.settings.UserTracker +import com.android.systemui.shared.notifications.domain.interactor.NotificationSettingsInteractor import com.android.systemui.statusbar.notification.collection.NotificationEntry import com.android.systemui.statusbar.notification.interruption.VisualInterruptionDecisionProvider.Decision import com.android.systemui.statusbar.notification.interruption.VisualInterruptionDecisionProvider.FullScreenIntentDecision @@ -72,7 +73,8 @@ constructor( private val packageManager: PackageManager, private val bubbles: Optional<Bubbles>, private val context: Context, - private val notificationManager: NotificationManager + private val notificationManager: NotificationManager, + private val settingsInteractor: NotificationSettingsInteractor ) : VisualInterruptionDecisionProvider { init { @@ -93,7 +95,8 @@ constructor( private constructor( val decision: DecisionImpl, override val uiEventId: UiEventEnum? = null, - override val eventLogData: EventLogData? = null + override val eventLogData: EventLogData? = null, + val isSpammy: Boolean = false, ) : Loggable { companion object { val unsuppressed = @@ -111,7 +114,8 @@ constructor( LoggableDecision( DecisionImpl(shouldInterrupt = false, logReason = suppressor.reason), uiEventId = suppressor.uiEventId, - eventLogData = suppressor.eventLogData + eventLogData = suppressor.eventLogData, + isSpammy = suppressor.isSpammy, ) } } @@ -183,8 +187,15 @@ constructor( if (NotificationAvalancheSuppression.isEnabled) { addFilter( - AvalancheSuppressor(avalancheProvider, systemClock, systemSettings, packageManager, - uiEventLogger, context, notificationManager) + AvalancheSuppressor( + avalancheProvider, + systemClock, + settingsInteractor, + packageManager, + uiEventLogger, + context, + notificationManager + ) ) avalancheProvider.register() } @@ -278,7 +289,9 @@ constructor( entry: NotificationEntry, loggableDecision: LoggableDecision ) { - logger.logDecision(type.name, entry, loggableDecision.decision) + if (!loggableDecision.isSpammy || logger.spew) { + logger.logDecision(type.name, entry, loggableDecision.decision) + } logEvents(entry, loggableDecision) } diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/interruption/VisualInterruptionSuppressor.kt b/packages/SystemUI/src/com/android/systemui/statusbar/notification/interruption/VisualInterruptionSuppressor.kt index ee797274deac..5fe75c0cb3f9 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/interruption/VisualInterruptionSuppressor.kt +++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/interruption/VisualInterruptionSuppressor.kt @@ -59,6 +59,10 @@ sealed interface VisualInterruptionSuppressor { /** Optional data to be logged in the EventLog when this suppresses an interruption. */ val eventLogData: EventLogData? + /** Whether the interruption is spammy and should be dropped under normal circumstances. */ + val isSpammy: Boolean + get() = false + /** * Called after the suppressor is added to the [VisualInterruptionDecisionProvider] but before * any other methods are called on the suppressor. @@ -76,7 +80,7 @@ abstract class VisualInterruptionCondition( constructor( types: Set<VisualInterruptionType>, reason: String - ) : this(types, reason, /* uiEventId = */ null) + ) : this(types, reason, /* uiEventId= */ null) /** @return true if these interruptions should be suppressed right now. */ abstract fun shouldSuppress(): Boolean @@ -87,12 +91,13 @@ abstract class VisualInterruptionFilter( override val types: Set<VisualInterruptionType>, override val reason: String, override val uiEventId: UiEventEnum? = null, - override val eventLogData: EventLogData? = null + override val eventLogData: EventLogData? = null, + override val isSpammy: Boolean = false, ) : VisualInterruptionSuppressor { constructor( types: Set<VisualInterruptionType>, reason: String - ) : this(types, reason, /* uiEventId = */ null) + ) : this(types, reason, /* uiEventId= */ null) /** * @param entry the notification to consider suppressing diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/shared/GroupHunAnimationFix.kt b/packages/SystemUI/src/com/android/systemui/statusbar/notification/shared/GroupHunAnimationFix.kt index 5867612d0b51..3b30c8623491 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/shared/GroupHunAnimationFix.kt +++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/shared/GroupHunAnimationFix.kt @@ -29,7 +29,7 @@ object GroupHunAnimationFix { val token: FlagToken get() = FlagToken(FLAG_NAME, isEnabled) - /** Are sections sorted by time? */ + /** Return whether the fix is enabled */ @JvmStatic inline val isEnabled get() = Flags.notificationGroupHunRemovalAnimationFix() diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/NotificationStackScrollLayout.java b/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/NotificationStackScrollLayout.java index 5d2b61b42db9..2f3b3a0fc2de 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/NotificationStackScrollLayout.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/NotificationStackScrollLayout.java @@ -1544,12 +1544,7 @@ public class NotificationStackScrollLayout public void setExpandedHeight(float height) { final boolean skipHeightUpdate = shouldSkipHeightUpdate(); - // when scene framework is enabled and in single shade, updateStackPosition is already - // called by updateTopPadding every time the stack moves, so skip it here to avoid - // flickering. - if (!SceneContainerFlag.isEnabled() || mShouldUseSplitNotificationShade) { - updateStackPosition(); - } + updateStackPosition(); if (!skipHeightUpdate) { mExpandedHeight = height; diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/NotificationStackScrollLayoutController.java b/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/NotificationStackScrollLayoutController.java index a072ea6ec3eb..fb1c5254cc5c 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/NotificationStackScrollLayoutController.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/NotificationStackScrollLayoutController.java @@ -124,6 +124,7 @@ import com.android.systemui.statusbar.notification.row.ExpandableView; import com.android.systemui.statusbar.notification.row.NotificationGuts; import com.android.systemui.statusbar.notification.row.NotificationGutsManager; import com.android.systemui.statusbar.notification.row.NotificationSnooze; +import com.android.systemui.statusbar.notification.shared.GroupHunAnimationFix; import com.android.systemui.statusbar.notification.shared.NotificationsHeadsUpRefactor; import com.android.systemui.statusbar.notification.stack.ui.viewbinder.NotificationListViewBinder; import com.android.systemui.statusbar.phone.HeadsUpAppearanceController; @@ -1987,6 +1988,10 @@ public class NotificationStackScrollLayoutController implements Dumpable { NotificationEntry entry = row.getEntry(); mHeadsUpAppearanceController.updateHeader(entry); mHeadsUpAppearanceController.updateHeadsUpAndPulsingRoundness(entry); + if (GroupHunAnimationFix.isEnabled() && !animatingAway) { + // invalidate list to make sure the row is sorted to the correct section + mHeadsUpManager.onEntryAnimatingAwayEnded(entry); + } }); } diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/ui/viewmodel/NotificationsPlaceholderViewModel.kt b/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/ui/viewmodel/NotificationsPlaceholderViewModel.kt index 1a7bc169ea2a..e8a784072808 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/ui/viewmodel/NotificationsPlaceholderViewModel.kt +++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/ui/viewmodel/NotificationsPlaceholderViewModel.kt @@ -91,6 +91,12 @@ constructor( val expandFraction: Flow<Float> = shadeInteractor.anyExpansion.dumpValue("expandFraction") /** + * The amount [0-1] that quick settings has been opened. At 0, the shade may be open or closed; + * at 1, the quick settings are open. + */ + val shadeToQsFraction: Flow<Float> = shadeInteractor.qsExpansion.dumpValue("shadeToQsFraction") + + /** * The amount in px that the notification stack should scroll due to internal expansion. This * should only happen when a notification expansion hits the bottom of the screen, so it is * necessary to scroll up to keep expanding the notification. diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/CentralSurfaces.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/CentralSurfaces.java index a0d4ca268e8c..ae311512db01 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/CentralSurfaces.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/CentralSurfaces.java @@ -261,8 +261,6 @@ public interface CentralSurfaces extends Dumpable, LifecycleOwner, CoreStartable boolean isScreenFullyOff(); - boolean isCameraAllowedByAdmin(); - boolean isGoingToSleep(); void notifyBiometricAuthModeChanged(); diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/CentralSurfacesCommandQueueCallbacks.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/CentralSurfacesCommandQueueCallbacks.java index c8a445033b0d..5209d0f1551e 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/CentralSurfacesCommandQueueCallbacks.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/CentralSurfacesCommandQueueCallbacks.java @@ -49,6 +49,7 @@ import com.android.systemui.dagger.qualifiers.Main; import com.android.systemui.emergency.EmergencyGesture; import com.android.systemui.emergency.EmergencyGestureModule.EmergencyGestureIntentFactory; import com.android.systemui.keyguard.WakefulnessLifecycle; +import com.android.systemui.keyguard.domain.interactor.KeyguardInteractor; import com.android.systemui.plugins.ActivityStarter; import com.android.systemui.qs.QSHost; import com.android.systemui.qs.QSPanelController; @@ -109,6 +110,7 @@ public class CentralSurfacesCommandQueueCallbacks implements CommandQueue.Callba private final Lazy<CameraLauncher> mCameraLauncherLazy; private final QuickSettingsController mQsController; private final QSHost mQSHost; + private final KeyguardInteractor mKeyguardInteractor; private static final VibrationAttributes HARDWARE_FEEDBACK_VIBRATION_ATTRIBUTES = VibrationAttributes.createForUsage(VibrationAttributes.USAGE_HARDWARE_FEEDBACK); @@ -148,6 +150,7 @@ public class CentralSurfacesCommandQueueCallbacks implements CommandQueue.Callba UserTracker userTracker, QSHost qsHost, ActivityStarter activityStarter, + KeyguardInteractor keyguardInteractor, EmergencyGestureIntentFactory emergencyGestureIntentFactory) { mCentralSurfaces = centralSurfaces; mQsController = quickSettingsController; @@ -176,7 +179,7 @@ public class CentralSurfacesCommandQueueCallbacks implements CommandQueue.Callba mCameraLauncherLazy = cameraLauncherLazy; mUserTracker = userTracker; mQSHost = qsHost; - + mKeyguardInteractor = keyguardInteractor; mVibrateOnOpening = resources.getBoolean(R.bool.config_vibrateOnIconAnimation); mCameraLaunchGestureVibrationEffect = getCameraGestureVibrationEffect( mVibratorOptional, resources); @@ -351,6 +354,8 @@ public class CentralSurfacesCommandQueueCallbacks implements CommandQueue.Callba } return; } + mKeyguardInteractor.onCameraLaunchDetected(source); + if (!mCentralSurfaces.isDeviceInteractive()) { mPowerManager.wakeUp(SystemClock.uptimeMillis(), PowerManager.WAKE_REASON_CAMERA_LAUNCH, "com.android.systemui:CAMERA_GESTURE"); @@ -383,6 +388,7 @@ public class CentralSurfacesCommandQueueCallbacks implements CommandQueue.Callba if (mStatusBarKeyguardViewManager.isBouncerShowing()) { mStatusBarKeyguardViewManager.reset(true /* hide */); } + mCentralSurfaces.startLaunchTransitionTimeout(); mCameraLauncherLazy.get().launchCamera(source, mPanelExpansionInteractor.isFullyCollapsed()); mCentralSurfaces.updateScrimController(); diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/CentralSurfacesEmptyImpl.kt b/packages/SystemUI/src/com/android/systemui/statusbar/phone/CentralSurfacesEmptyImpl.kt index 88d3e0718fa6..d4f2a93c025b 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/CentralSurfacesEmptyImpl.kt +++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/CentralSurfacesEmptyImpl.kt @@ -34,72 +34,127 @@ import com.android.systemui.statusbar.notification.row.ExpandableNotificationRow */ abstract class CentralSurfacesEmptyImpl : CentralSurfaces { override val lifecycle = LifecycleRegistry(this) + override fun updateIsKeyguard() = false + override fun updateIsKeyguard(forceStateChange: Boolean) = false + override fun getKeyguardMessageArea(): AuthKeyguardMessageArea? = null + override fun isLaunchingActivityOverLockscreen() = false + override fun isDismissingShadeForActivityLaunch() = false + override fun onKeyguardViewManagerStatesUpdated() {} + override fun getCommandQueuePanelsEnabled() = false + override fun showWirelessChargingAnimation(batteryLevel: Int) {} + override fun checkBarModes() {} + override fun updateBubblesVisibility() {} + override fun setInteracting(barWindow: Int, interacting: Boolean) {} + override fun getDisplayWidth() = 0f + override fun getDisplayHeight() = 0f + override fun showKeyguard() {} + override fun hideKeyguard() = false + override fun showKeyguardImpl() {} + override fun fadeKeyguardAfterLaunchTransition( beforeFading: Runnable?, endRunnable: Runnable?, cancelRunnable: Runnable?, ) {} + override fun startLaunchTransitionTimeout() {} + override fun hideKeyguardImpl(forceStateChange: Boolean) = false + override fun keyguardGoingAway() {} + override fun setKeyguardFadingAway(startTime: Long, delay: Long, fadeoutDuration: Long) {} + override fun finishKeyguardFadingAway() {} + override fun userActivity() {} + override fun endAffordanceLaunch() {} + override fun shouldKeyguardHideImmediately() = false + override fun showBouncerWithDimissAndCancelIfKeyguard( performAction: OnDismissAction?, cancelAction: Runnable?, ) {} + override fun getNavigationBarView(): NavigationBarView? = null + override fun setBouncerShowing(bouncerShowing: Boolean) {} + override fun isScreenFullyOff() = false - override fun isCameraAllowedByAdmin() = false + override fun isGoingToSleep() = false + override fun notifyBiometricAuthModeChanged() {} + override fun setTransitionToFullShadeProgress(transitionToFullShadeProgress: Float) {} + override fun setPrimaryBouncerHiddenFraction(expansion: Float) {} + override fun updateScrimController() {} + override fun shouldIgnoreTouch() = false + override fun isDeviceInteractive() = false + override fun handleExternalShadeWindowTouch(event: MotionEvent?) {} + override fun handleCommunalHubTouch(event: MotionEvent?) {} + override fun awakenDreams() {} + override fun isBouncerShowing() = false + override fun isBouncerShowingScrimmed() = false + override fun updateNotificationPanelTouchState() {} + override fun getRotation() = 0 + override fun setBarStateForTest(state: Int) {} + override fun acquireGestureWakeLock(time: Long) {} + override fun resendMessage(msg: Int) {} + override fun resendMessage(msg: Any?) {} + override fun setLastCameraLaunchSource(source: Int) {} + override fun setLaunchCameraOnFinishedGoingToSleep(launch: Boolean) {} + override fun setLaunchCameraOnFinishedWaking(launch: Boolean) {} + override fun setLaunchEmergencyActionOnFinishedGoingToSleep(launch: Boolean) {} + override fun setLaunchEmergencyActionOnFinishedWaking(launch: Boolean) {} + override fun getQSPanelController(): QSPanelController? = null + override fun getDisplayDensity() = 0f + override fun setIsLaunchingActivityOverLockscreen( isLaunchingActivityOverLockscreen: Boolean, dismissShade: Boolean, ) {} + override fun getAnimatorControllerFromNotification( associatedView: ExpandableNotificationRow?, ): ActivityTransitionAnimator.Controller? = null diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/CentralSurfacesImpl.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/CentralSurfacesImpl.java index 462ae7ab39cb..b6de78e70994 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/CentralSurfacesImpl.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/CentralSurfacesImpl.java @@ -47,7 +47,6 @@ import android.app.StatusBarManager; import android.app.TaskInfo; import android.app.UiModeManager; import android.app.WallpaperManager; -import android.app.admin.DevicePolicyManager; import android.content.BroadcastReceiver; import android.content.Context; import android.content.Intent; @@ -883,8 +882,6 @@ public class CentralSurfacesImpl implements CoreStartable, CentralSurfaces { // start old BaseStatusBar.start(). mWindowManagerService = WindowManagerGlobal.getWindowManagerService(); - mDevicePolicyManager = (DevicePolicyManager) mContext.getSystemService( - Context.DEVICE_POLICY_SERVICE); mAccessibilityManager = (AccessibilityManager) mContext.getSystemService(Context.ACCESSIBILITY_SERVICE); @@ -2627,6 +2624,7 @@ public class CentralSurfacesImpl implements CoreStartable, CentralSurfaces { mStackScrollerController.updateSensitivenessForOccludedWakeup(); } if (mLaunchCameraWhenFinishedWaking) { + startLaunchTransitionTimeout(); mCameraLauncherLazy.get().launchCamera(mLastCameraLaunchSource, mShadeSurface.isFullyCollapsed()); mLaunchCameraWhenFinishedWaking = false; @@ -2701,21 +2699,6 @@ public class CentralSurfacesImpl implements CoreStartable, CentralSurfaces { } @Override - public boolean isCameraAllowedByAdmin() { - if (mDevicePolicyManager.getCameraDisabled(null, - mLockscreenUserManager.getCurrentUserId())) { - return false; - } else if (mKeyguardStateController.isShowing() - && mStatusBarKeyguardViewManager.isSecure()) { - // Check if the admin has disabled the camera specifically for the keyguard - return (mDevicePolicyManager.getKeyguardDisabledFeatures(null, - mLockscreenUserManager.getCurrentUserId()) - & DevicePolicyManager.KEYGUARD_DISABLE_SECURE_CAMERA) == 0; - } - return true; - } - - @Override public boolean isGoingToSleep() { return mWakefulnessLifecycle.getWakefulness() == WakefulnessLifecycle.WAKEFULNESS_GOING_TO_SLEEP; @@ -2864,7 +2847,6 @@ public class CentralSurfacesImpl implements CoreStartable, CentralSurfaces { protected boolean mDeviceInteractive; - protected DevicePolicyManager mDevicePolicyManager; private final PowerManager mPowerManager; protected StatusBarKeyguardViewManager mStatusBarKeyguardViewManager; @@ -3013,7 +2995,7 @@ public class CentralSurfacesImpl implements CoreStartable, CentralSurfaces { @Override public void onFalse() { // Hides quick settings, bouncer, and quick-quick settings. - mStatusBarKeyguardViewManager.reset(true); + mStatusBarKeyguardViewManager.reset(true, /* isFalsingReset= */true); } }; diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/DozeServiceHost.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/DozeServiceHost.java index a32d5fef58eb..ca1fb78bdb42 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/DozeServiceHost.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/DozeServiceHost.java @@ -437,6 +437,13 @@ public final class DozeServiceHost implements DozeHost { mNotificationShadeWindowController.setDozeScreenBrightness(brightness); } + + @Override + public void setDozeScreenBrightnessFloat(float brightness) { + mDozeLog.traceDozeScreenBrightnessFloat(brightness); + mNotificationShadeWindowController.setDozeScreenBrightnessFloat(brightness); + } + @Override public void setAodDimmingScrim(float scrimOpacity) { mDozeLog.traceSetAodDimmingScrim(scrimOpacity); diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/HeadsUpManagerPhone.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/HeadsUpManagerPhone.java index e08dbb9df7dc..25d9cc76fe3d 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/HeadsUpManagerPhone.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/HeadsUpManagerPhone.java @@ -117,7 +117,7 @@ public class HeadsUpManagerPhone extends BaseHeadsUpManager implements @Override public HeadsUpEntryPhone acquire() { - NotificationsHeadsUpRefactor.assertInLegacyMode(); + NotificationThrottleHun.assertInLegacyMode(); if (!mPoolObjects.isEmpty()) { return mPoolObjects.pop(); } @@ -126,7 +126,7 @@ public class HeadsUpManagerPhone extends BaseHeadsUpManager implements @Override public boolean release(@NonNull HeadsUpEntryPhone instance) { - NotificationsHeadsUpRefactor.assertInLegacyMode(); + NotificationThrottleHun.assertInLegacyMode(); mPoolObjects.push(instance); return true; } @@ -389,10 +389,13 @@ public class HeadsUpManagerPhone extends BaseHeadsUpManager implements // OnReorderingAllowedListener: private final OnReorderingAllowedListener mOnReorderingAllowedListener = () -> { - mAnimationStateHandler.setHeadsUpGoingAwayAnimationsAllowed(false); if (NotificationThrottleHun.isEnabled()) { mAvalancheController.setEnableAtRuntime(true); + if (mEntriesToRemoveWhenReorderingAllowed.isEmpty()) { + return; + } } + mAnimationStateHandler.setHeadsUpGoingAwayAnimationsAllowed(false); for (NotificationEntry entry : mEntriesToRemoveWhenReorderingAllowed) { if (isHeadsUpEntry(entry.getKey())) { // Maybe the heads-up was removed already @@ -425,7 +428,7 @@ public class HeadsUpManagerPhone extends BaseHeadsUpManager implements @NonNull @Override protected HeadsUpEntry createHeadsUpEntry(NotificationEntry entry) { - if (NotificationsHeadsUpRefactor.isEnabled()) { + if (NotificationThrottleHun.isEnabled()) { return new HeadsUpEntryPhone(entry); } else { HeadsUpEntryPhone headsUpEntry = mEntryPool.acquire(); @@ -451,7 +454,7 @@ public class HeadsUpManagerPhone extends BaseHeadsUpManager implements @Override protected void onEntryRemoved(HeadsUpEntry headsUpEntry) { super.onEntryRemoved(headsUpEntry); - if (!NotificationsHeadsUpRefactor.isEnabled()) { + if (!NotificationThrottleHun.isEnabled()) { mEntryPool.release((HeadsUpEntryPhone) headsUpEntry); } updateTopHeadsUpFlow(); diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarKeyguardViewManager.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarKeyguardViewManager.java index 41b69a733bd3..0b8f18e8f286 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarKeyguardViewManager.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarKeyguardViewManager.java @@ -708,7 +708,7 @@ public class StatusBarKeyguardViewManager implements RemoteInputController.Callb * Shows the notification keyguard or the bouncer depending on * {@link #needsFullscreenBouncer()}. */ - protected void showBouncerOrKeyguard(boolean hideBouncerWhenShowing) { + protected void showBouncerOrKeyguard(boolean hideBouncerWhenShowing, boolean isFalsingReset) { boolean isDozing = mDozing; if (Flags.simPinRaceConditionOnRestart()) { KeyguardState toState = mKeyguardTransitionInteractor.getTransitionState().getValue() @@ -734,8 +734,12 @@ public class StatusBarKeyguardViewManager implements RemoteInputController.Callb mPrimaryBouncerInteractor.show(/* isScrimmed= */ true); } } - } else { - Log.e(TAG, "Attempted to show the sim bouncer when it is already showing."); + } else if (!isFalsingReset) { + // Falsing resets can cause this to flicker, so don't reset in this case + Log.i(TAG, "Sim bouncer is already showing, issuing a refresh"); + mPrimaryBouncerInteractor.hide(); + mPrimaryBouncerInteractor.show(/* isScrimmed= */ true); + } } else { mCentralSurfaces.showKeyguard(); @@ -957,6 +961,10 @@ public class StatusBarKeyguardViewManager implements RemoteInputController.Callb @Override public void reset(boolean hideBouncerWhenShowing) { + reset(hideBouncerWhenShowing, /* isFalsingReset= */false); + } + + public void reset(boolean hideBouncerWhenShowing, boolean isFalsingReset) { if (mKeyguardStateController.isShowing() && !bouncerIsAnimatingAway()) { final boolean isOccluded = mKeyguardStateController.isOccluded(); // Hide quick settings. @@ -968,7 +976,7 @@ public class StatusBarKeyguardViewManager implements RemoteInputController.Callb hideBouncer(false /* destroyView */); } } else { - showBouncerOrKeyguard(hideBouncerWhenShowing); + showBouncerOrKeyguard(hideBouncerWhenShowing, isFalsingReset); } if (hideBouncerWhenShowing) { hideAlternateBouncer(true); @@ -1106,7 +1114,9 @@ public class StatusBarKeyguardViewManager implements RemoteInputController.Callb SysUiStatsLog.KEYGUARD_STATE_CHANGED__STATE__OCCLUDED); if (mCentralSurfaces.isLaunchingActivityOverLockscreen()) { final Runnable postCollapseAction = () -> { - mNotificationShadeWindowController.setKeyguardOccluded(isOccluded); + if (!Flags.useTransitionsForKeyguardOccluded()) { + mNotificationShadeWindowController.setKeyguardOccluded(isOccluded); + } reset(true /* hideBouncerWhenShowing */); }; if (mCentralSurfaces.isDismissingShadeForActivityLaunch()) { @@ -1122,7 +1132,9 @@ public class StatusBarKeyguardViewManager implements RemoteInputController.Callb SysUiStatsLog.write(SysUiStatsLog.KEYGUARD_STATE_CHANGED, SysUiStatsLog.KEYGUARD_STATE_CHANGED__STATE__SHOWN); } - mNotificationShadeWindowController.setKeyguardOccluded(isOccluded); + if (!Flags.useTransitionsForKeyguardOccluded()) { + mNotificationShadeWindowController.setKeyguardOccluded(isOccluded); + } // setDozing(false) will call reset once we stop dozing. Also, if we're going away, there's // no need to reset the keyguard views as we'll be gone shortly. Resetting now could cause diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/pipeline/satellite/data/prod/DeviceBasedSatelliteRepositoryImpl.kt b/packages/SystemUI/src/com/android/systemui/statusbar/pipeline/satellite/data/prod/DeviceBasedSatelliteRepositoryImpl.kt index a7c5f78e5b69..03ec41d5af46 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/pipeline/satellite/data/prod/DeviceBasedSatelliteRepositoryImpl.kt +++ b/packages/SystemUI/src/com/android/systemui/statusbar/pipeline/satellite/data/prod/DeviceBasedSatelliteRepositoryImpl.kt @@ -20,6 +20,7 @@ import android.os.OutcomeReceiver import android.telephony.TelephonyCallback import android.telephony.TelephonyManager import android.telephony.satellite.NtnSignalStrengthCallback +import android.telephony.satellite.SatelliteCommunicationAllowedStateCallback import android.telephony.satellite.SatelliteManager import android.telephony.satellite.SatelliteManager.SATELLITE_RESULT_SUCCESS import android.telephony.satellite.SatelliteModemStateCallback @@ -37,7 +38,6 @@ import com.android.systemui.log.core.MessagePrinter import com.android.systemui.statusbar.pipeline.dagger.DeviceBasedSatelliteInputLog import com.android.systemui.statusbar.pipeline.dagger.VerboseDeviceBasedSatelliteInputLog import com.android.systemui.statusbar.pipeline.satellite.data.RealDeviceBasedSatelliteRepository -import com.android.systemui.statusbar.pipeline.satellite.data.prod.DeviceBasedSatelliteRepositoryImpl.Companion.POLLING_INTERVAL_MS import com.android.systemui.statusbar.pipeline.satellite.data.prod.SatelliteSupport.Companion.whenSupported import com.android.systemui.statusbar.pipeline.satellite.data.prod.SatelliteSupport.NotSupported import com.android.systemui.statusbar.pipeline.satellite.data.prod.SatelliteSupport.Supported @@ -60,11 +60,9 @@ import kotlinx.coroutines.flow.MutableStateFlow import kotlinx.coroutines.flow.SharingStarted import kotlinx.coroutines.flow.StateFlow import kotlinx.coroutines.flow.collectLatest -import kotlinx.coroutines.flow.distinctUntilChanged import kotlinx.coroutines.flow.flatMapLatest import kotlinx.coroutines.flow.flowOf import kotlinx.coroutines.flow.flowOn -import kotlinx.coroutines.flow.map import kotlinx.coroutines.flow.mapNotNull import kotlinx.coroutines.flow.onStart import kotlinx.coroutines.flow.stateIn @@ -122,15 +120,9 @@ sealed interface SatelliteSupport { } /** - * Basically your everyday run-of-the-mill system service listener, with three notable exceptions. + * Basically your everyday run-of-the-mill system service listener, with two notable exceptions. * - * First, there is an availability bit that we are tracking via [SatelliteManager]. See - * [isSatelliteAllowedForCurrentLocation] for the implementation details. The thing to note about - * this bit is that there is no callback that exists. Therefore we implement a simple polling - * mechanism here. Since the underlying bit is location-dependent, we simply poll every hour (see - * [POLLING_INTERVAL_MS]) and see what the current state is. - * - * Secondly, there are cases when simply requesting information from SatelliteManager can fail. See + * First, there are cases when simply requesting information from SatelliteManager can fail. See * [SatelliteSupport] for details on how we track the state. What's worth noting here is that * SUPPORTED is a stronger guarantee than [satelliteManager] being null. Therefore, the fundamental * data flows here ([connectionState], [signalStrength],...) are wrapped in the convenience method @@ -138,7 +130,7 @@ sealed interface SatelliteSupport { * [SupportedSatelliteManager], we can guarantee that the manager is non-null AND that it has told * us that satellite is supported. Therefore, we don't expect exceptions to be thrown. * - * Lastly, this class is designed to wait a full minute of process uptime before making any requests + * Second, this class is designed to wait a full minute of process uptime before making any requests * to the satellite manager. The hope is that by waiting we don't have to retry due to a modem that * is still booting up or anything like that. We can tune or remove this behavior in the future if * necessary. @@ -158,8 +150,6 @@ constructor( private val satelliteManager: SatelliteManager? - override val isSatelliteAllowedForCurrentLocation: MutableStateFlow<Boolean> - // Some calls into satellite manager will throw exceptions if it is not supported. // This is never expected to change after boot, but may need to be retried in some cases @get:VisibleForTesting @@ -221,8 +211,6 @@ constructor( init { satelliteManager = satelliteManagerOpt.getOrNull() - isSatelliteAllowedForCurrentLocation = MutableStateFlow(false) - if (satelliteManager != null) { // Outer scope launch allows us to delay until MIN_UPTIME scope.launch { @@ -233,10 +221,7 @@ constructor( { "Checked for system support. support=$str1" }, ) - // Second, launch a job to poll for service availability based on location - scope.launch { pollForAvailabilityBasedOnLocation() } - - // Third, register a listener to let us know if there are changes to support + // Second, register a listener to let us know if there are changes to support scope.launch { listenForChangesToSatelliteSupport(satelliteManager) } } } else { @@ -259,28 +244,43 @@ constructor( return sm.checkSatelliteSupported() } - /* - * As there is no listener available for checking satellite allowed, we must poll the service. - * Defaulting to polling at most once every 20m while active. Subsequent OOS events will restart - * the job, so a flaky connection might cause more frequent checks. - */ - private suspend fun pollForAvailabilityBasedOnLocation() { + override val isSatelliteAllowedForCurrentLocation = satelliteSupport .whenSupported( - supported = ::isSatelliteAllowedHasListener, + supported = ::isSatelliteAvailableFlow, orElse = flowOf(false), retrySignal = telephonyProcessCrashedEvent, ) - .collectLatest { hasSubscribers -> - if (hasSubscribers) { - while (true) { - logBuffer.i { "requestIsCommunicationAllowedForCurrentLocation" } - checkIsSatelliteAllowed() - delay(POLLING_INTERVAL_MS) + .stateIn(scope, SharingStarted.Lazily, false) + + private fun isSatelliteAvailableFlow(sm: SupportedSatelliteManager): Flow<Boolean> = + conflatedCallbackFlow { + val callback = SatelliteCommunicationAllowedStateCallback { allowed -> + logBuffer.i({ bool1 = allowed }) { + "onSatelliteCommunicationAllowedStateChanged: $bool1" + } + + trySend(allowed) + } + + var registered = false + try { + sm.registerForCommunicationAllowedStateChanged( + bgDispatcher.asExecutor(), + callback + ) + registered = true + } catch (e: Exception) { + logBuffer.e("Error calling registerForCommunicationAllowedStateChanged", e) + } + + awaitClose { + if (registered) { + sm.unregisterForCommunicationAllowedStateChanged(callback) } } } - } + .flowOn(bgDispatcher) /** * Register a callback with [SatelliteManager] to let us know if there is a change in satellite @@ -410,14 +410,6 @@ constructor( } } - /** - * Signal that we should start polling [checkIsSatelliteAllowed]. We only need to poll if there - * are active listeners to [isSatelliteAllowedForCurrentLocation] - */ - @SuppressWarnings("unused") - private fun isSatelliteAllowedHasListener(sm: SupportedSatelliteManager): Flow<Boolean> = - isSatelliteAllowedForCurrentLocation.subscriptionCount.map { it > 0 }.distinctUntilChanged() - override val connectionState = satelliteSupport .whenSupported( @@ -485,28 +477,6 @@ constructor( } .flowOn(bgDispatcher) - /** Fire off a request to check for satellite availability. Always runs on the bg context */ - private suspend fun checkIsSatelliteAllowed() = - withContext(bgDispatcher) { - satelliteManager?.requestIsCommunicationAllowedForCurrentLocation( - bgDispatcher.asExecutor(), - object : OutcomeReceiver<Boolean, SatelliteManager.SatelliteException> { - override fun onError(e: SatelliteManager.SatelliteException) { - logBuffer.e( - "Found exception when checking availability", - e, - ) - isSatelliteAllowedForCurrentLocation.value = false - } - - override fun onResult(allowed: Boolean) { - logBuffer.i { "isSatelliteAllowedForCurrentLocation: $allowed" } - isSatelliteAllowedForCurrentLocation.value = allowed - } - } - ) - } - private suspend fun SatelliteManager.checkSatelliteSupported(): SatelliteSupport = suspendCancellableCoroutine { continuation -> val cb = @@ -546,9 +516,6 @@ constructor( } companion object { - // TTL for satellite polling is twenty minutes - const val POLLING_INTERVAL_MS: Long = 1000 * 60 * 20 - // Let the system boot up and stabilize before we check for system support const val MIN_UPTIME: Long = 1000 * 60 diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/policy/AvalancheController.kt b/packages/SystemUI/src/com/android/systemui/statusbar/policy/AvalancheController.kt index a96382672235..5ba5c0685941 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/policy/AvalancheController.kt +++ b/packages/SystemUI/src/com/android/systemui/statusbar/policy/AvalancheController.kt @@ -54,6 +54,7 @@ constructor( // allowed again. logDroppedHunsInBackground(getWaitingKeys().size) clearNext() + headsUpEntryShowing = null } if (field != value) { field = value @@ -222,15 +223,19 @@ constructor( /** * Returns duration based on - * 1) Whether HeadsUpEntry is the last one tracked byAvalancheController + * 1) Whether HeadsUpEntry is the last one tracked by AvalancheController * 2) The priority of the top HUN in the next batch Used by * BaseHeadsUpManager.HeadsUpEntry.calculateFinishTime to shorten display duration. */ - fun getDurationMs(entry: HeadsUpEntry, autoDismissMs: Int): Int { + fun getDurationMs(entry: HeadsUpEntry?, autoDismissMs: Int): Int { if (!isEnabled()) { // Use default duration, like we did before AvalancheController existed return autoDismissMs } + if (entry == null) { + // This should never happen + return autoDismissMs + } val showingList: MutableList<HeadsUpEntry> = mutableListOf() if (headsUpEntryShowing != null) { showingList.add(headsUpEntryShowing!!) diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/policy/BaseHeadsUpManager.java b/packages/SystemUI/src/com/android/systemui/statusbar/policy/BaseHeadsUpManager.java index dcd9caec0be3..37869587528e 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/policy/BaseHeadsUpManager.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/policy/BaseHeadsUpManager.java @@ -171,7 +171,6 @@ public abstract class BaseHeadsUpManager implements HeadsUpManager { mLogger.logShowNotificationRequest(entry); Runnable runnable = () -> { - // TODO(b/315362456) log outside runnable too mLogger.logShowNotification(entry); // Add new entry and begin managing it @@ -244,8 +243,10 @@ public abstract class BaseHeadsUpManager implements HeadsUpManager { return; } // TODO(b/328390331) move accessibility events to the view layer - headsUpEntry.mEntry.sendAccessibilityEvent(AccessibilityEvent.TYPE_WINDOW_CONTENT_CHANGED); - + if (headsUpEntry.mEntry != null) { + headsUpEntry.mEntry.sendAccessibilityEvent( + AccessibilityEvent.TYPE_WINDOW_CONTENT_CHANGED); + } if (shouldHeadsUpAgain) { headsUpEntry.updateEntry(true /* updatePostTime */, "updateNotification"); if (headsUpEntry != null) { @@ -334,6 +335,9 @@ public abstract class BaseHeadsUpManager implements HeadsUpManager { } protected boolean shouldHeadsUpBecomePinned(@NonNull NotificationEntry entry) { + if (entry == null) { + return false; + } final HeadsUpEntry headsUpEntry = getHeadsUpEntry(entry.getKey()); if (headsUpEntry == null) { // This should not happen since shouldHeadsUpBecomePinned is always called after adding @@ -344,6 +348,15 @@ public abstract class BaseHeadsUpManager implements HeadsUpManager { } protected boolean hasFullScreenIntent(@NonNull NotificationEntry entry) { + if (entry == null) { + return false; + } + if (entry.getSbn() == null) { + return false; + } + if (entry.getSbn().getNotification() == null) { + return false; + } return entry.getSbn().getNotification().fullScreenIntent != null; } @@ -426,7 +439,7 @@ public abstract class BaseHeadsUpManager implements HeadsUpManager { onEntryRemoved(finalHeadsUpEntry); // TODO(b/328390331) move accessibility events to the view layer entry.sendAccessibilityEvent(AccessibilityEvent.TYPE_WINDOW_CONTENT_CHANGED); - if (NotificationsHeadsUpRefactor.isEnabled()) { + if (NotificationThrottleHun.isEnabled()) { finalHeadsUpEntry.cancelAutoRemovalCallbacks("removeEntry"); } else { finalHeadsUpEntry.reset(); @@ -451,6 +464,15 @@ public abstract class BaseHeadsUpManager implements HeadsUpManager { } /** + * Called to notify the listeners that the HUN animating away animation has ended. + */ + public void onEntryAnimatingAwayEnded(@NonNull NotificationEntry entry) { + for (OnHeadsUpChangedListener listener : mListeners) { + listener.onHeadsUpAnimatingAwayEnded(entry); + } + } + + /** * Manager-specific logic, that should occur, when the entry is updated, and its posted time has * changed. * @@ -499,6 +521,9 @@ public abstract class BaseHeadsUpManager implements HeadsUpManager { keySet.addAll(mAvalancheController.getWaitingKeys()); for (String key : keySet) { HeadsUpEntry entry = getHeadsUpEntry(key); + if (entry.mEntry == null) { + continue; + } String packageName = entry.mEntry.getSbn().getPackageName(); String snoozeKey = snoozeKey(packageName, mUser); mLogger.logPackageSnoozed(snoozeKey); @@ -566,7 +591,7 @@ public abstract class BaseHeadsUpManager implements HeadsUpManager { pw.print(" now="); pw.println(mSystemClock.elapsedRealtime()); pw.print(" mUser="); pw.println(mUser); for (HeadsUpEntry entry: mHeadsUpEntryMap.values()) { - pw.print(" HeadsUpEntry="); pw.println(entry.mEntry); + pw.println(entry.mEntry == null ? "null" : entry.mEntry); } int n = mSnoozedPackages.size(); pw.println(" snoozed packages: " + n); @@ -586,7 +611,7 @@ public abstract class BaseHeadsUpManager implements HeadsUpManager { private boolean hasPinnedNotificationInternal() { for (String key : mHeadsUpEntryMap.keySet()) { HeadsUpEntry entry = getHeadsUpEntry(key); - if (entry.mEntry.isRowPinned()) { + if (entry.mEntry != null && entry.mEntry.isRowPinned()) { return true; } } @@ -611,7 +636,7 @@ public abstract class BaseHeadsUpManager implements HeadsUpManager { // when the user unpinned all of HUNs by moving one HUN, all of HUNs should not stay // on the screen. if (userUnPinned && headsUpEntry.mEntry != null) { - if (headsUpEntry.mEntry.mustStayOnScreen()) { + if (headsUpEntry.mEntry != null && headsUpEntry.mEntry.mustStayOnScreen()) { headsUpEntry.mEntry.setHeadsUpIsVisible(); } } @@ -687,7 +712,7 @@ public abstract class BaseHeadsUpManager implements HeadsUpManager { return true; } return headsUpEntry == null || headsUpEntry.wasShownLongEnough() - || headsUpEntry.mEntry.isRowDismissed(); + || (headsUpEntry.mEntry != null && headsUpEntry.mEntry.isRowDismissed()); } /** @@ -743,7 +768,7 @@ public abstract class BaseHeadsUpManager implements HeadsUpManager { @Nullable private Runnable mCancelRemoveRunnable; public HeadsUpEntry() { - NotificationsHeadsUpRefactor.assertInLegacyMode(); + NotificationThrottleHun.assertInLegacyMode(); } public HeadsUpEntry(NotificationEntry entry) { @@ -754,7 +779,7 @@ public abstract class BaseHeadsUpManager implements HeadsUpManager { /** Attach a NotificationEntry. */ public void setEntry(@NonNull final NotificationEntry entry) { - NotificationsHeadsUpRefactor.assertInLegacyMode(); + NotificationThrottleHun.assertInLegacyMode(); setEntry(entry, createRemoveRunnable(entry)); } @@ -866,6 +891,14 @@ public abstract class BaseHeadsUpManager implements HeadsUpManager { } public int compareNonTimeFields(HeadsUpEntry headsUpEntry) { + if (mEntry == null && headsUpEntry.mEntry == null) { + return 0; + } else if (headsUpEntry.mEntry == null) { + return -1; + } else if (mEntry == null) { + return 1; + } + boolean selfFullscreen = hasFullScreenIntent(mEntry); boolean otherFullscreen = hasFullScreenIntent(headsUpEntry.mEntry); if (selfFullscreen && !otherFullscreen) { @@ -892,6 +925,13 @@ public abstract class BaseHeadsUpManager implements HeadsUpManager { } public int compareTo(@NonNull HeadsUpEntry headsUpEntry) { + if (mEntry == null && headsUpEntry.mEntry == null) { + return 0; + } else if (headsUpEntry.mEntry == null) { + return -1; + } else if (mEntry == null) { + return 1; + } boolean isPinned = mEntry.isRowPinned(); boolean otherPinned = headsUpEntry.mEntry.isRowPinned(); if (isPinned && !otherPinned) { @@ -936,7 +976,7 @@ public abstract class BaseHeadsUpManager implements HeadsUpManager { } public void reset() { - NotificationsHeadsUpRefactor.assertInLegacyMode(); + NotificationThrottleHun.assertInLegacyMode(); cancelAutoRemovalCallbacks("reset()"); mEntry = null; mRemoveRunnable = null; @@ -956,7 +996,7 @@ public abstract class BaseHeadsUpManager implements HeadsUpManager { mLogger.logAutoRemoveCanceled(mEntry, reason); } }; - if (isHeadsUpEntry(this.mEntry.getKey())) { + if (mEntry != null && isHeadsUpEntry(mEntry.getKey())) { mAvalancheController.update(this, runnable, reason + " cancelAutoRemovalCallbacks"); } else { // Just removed diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/policy/HeadsUpManager.kt b/packages/SystemUI/src/com/android/systemui/statusbar/policy/HeadsUpManager.kt index 28a2a1f49bf6..fcf77d5526d4 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/policy/HeadsUpManager.kt +++ b/packages/SystemUI/src/com/android/systemui/statusbar/policy/HeadsUpManager.kt @@ -42,6 +42,7 @@ interface HeadsUpManager : Dumpable { * should be ranked higher and 0 if they are equal. */ fun compare(a: NotificationEntry?, b: NotificationEntry?): Int + /** * Extends the lifetime of the currently showing pulsing notification so that the pulse lasts * longer. @@ -184,6 +185,8 @@ interface HeadsUpManager : Dumpable { fun unpinAll(userUnPinned: Boolean) fun updateNotification(key: String, shouldHeadsUpAgain: Boolean) + + fun onEntryAnimatingAwayEnded(entry: NotificationEntry) } /** Sets the animation state of the HeadsUpManager. */ @@ -204,41 +207,77 @@ interface OnHeadsUpPhoneListenerChange { /* No op impl of HeadsUpManager. */ class HeadsUpManagerEmptyImpl @Inject constructor() : HeadsUpManager { override val allEntries = Stream.empty<NotificationEntry>() + override fun addHeadsUpPhoneListener(listener: OnHeadsUpPhoneListenerChange) {} + override fun addListener(listener: OnHeadsUpChangedListener) {} + override fun addSwipedOutNotification(key: String) {} + override fun canRemoveImmediately(key: String) = false + override fun compare(a: NotificationEntry?, b: NotificationEntry?) = 0 + override fun dump(pw: PrintWriter, args: Array<out String>) {} + override fun extendHeadsUp() {} + override fun getEarliestRemovalTime(key: String?) = 0L + override fun getTouchableRegion(): Region? = null + override fun getTopEntry() = null + override fun hasPinnedHeadsUp() = false + override fun isHeadsUpEntry(key: String) = false + override fun isHeadsUpAnimatingAwayValue() = false + override fun isSnoozed(packageName: String) = false + override fun isSticky(key: String?) = false + override fun isTrackingHeadsUp() = false + override fun onExpandingFinished() {} + override fun releaseAllImmediately() {} + override fun removeListener(listener: OnHeadsUpChangedListener) {} + override fun removeNotification(key: String, releaseImmediately: Boolean) = false + override fun removeNotification(key: String, releaseImmediately: Boolean, animate: Boolean) = false + override fun setAnimationStateHandler(handler: AnimationStateHandler) {} + override fun setExpanded(entry: NotificationEntry, expanded: Boolean) {} + override fun setGutsShown(entry: NotificationEntry, gutsShown: Boolean) {} + override fun setHeadsUpAnimatingAway(headsUpAnimatingAway: Boolean) {} + override fun setRemoteInputActive(entry: NotificationEntry, remoteInputActive: Boolean) {} + override fun setTrackingHeadsUp(tracking: Boolean) {} + override fun setUser(user: Int) {} + override fun setUserActionMayIndirectlyRemove(entry: NotificationEntry) {} + override fun shouldSwallowClick(key: String): Boolean = false + override fun showNotification(entry: NotificationEntry) {} + override fun snooze() {} + override fun unpinAll(userUnPinned: Boolean) {} + override fun updateNotification(key: String, alert: Boolean) {} + + override fun onEntryAnimatingAwayEnded(entry: NotificationEntry) {} } @Module diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/policy/OnHeadsUpChangedListener.java b/packages/SystemUI/src/com/android/systemui/statusbar/policy/OnHeadsUpChangedListener.java index 86998ab2fdd9..de3bf0462d5b 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/policy/OnHeadsUpChangedListener.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/policy/OnHeadsUpChangedListener.java @@ -48,4 +48,9 @@ public interface OnHeadsUpChangedListener { * @param isHeadsUp whether the notification is now a headsUp notification */ default void onHeadsUpStateChanged(@NonNull NotificationEntry entry, boolean isHeadsUp) {} + + /** + * Called on HUN disappearing animation ends + */ + default void onHeadsUpAnimatingAwayEnded(@NonNull NotificationEntry entry) {} } diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/policy/PolicyModule.kt b/packages/SystemUI/src/com/android/systemui/statusbar/policy/PolicyModule.kt index cf9a78f1c11c..21ec14fc7f03 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/policy/PolicyModule.kt +++ b/packages/SystemUI/src/com/android/systemui/statusbar/policy/PolicyModule.kt @@ -20,6 +20,7 @@ import android.os.UserManager.DISALLOW_CAMERA_TOGGLE import android.os.UserManager.DISALLOW_CONFIG_LOCATION import android.os.UserManager.DISALLOW_MICROPHONE_TOGGLE import android.os.UserManager.DISALLOW_SHARE_LOCATION +import com.android.systemui.Flags import com.android.systemui.qs.QsEventLogger import com.android.systemui.qs.pipeline.shared.TileSpec import com.android.systemui.qs.tileimpl.QSTileImpl @@ -67,25 +68,18 @@ import com.android.systemui.qs.tiles.viewmodel.QSTileConfig import com.android.systemui.qs.tiles.viewmodel.QSTilePolicy import com.android.systemui.qs.tiles.viewmodel.QSTileUIConfig import com.android.systemui.qs.tiles.viewmodel.QSTileViewModel +import com.android.systemui.qs.tiles.viewmodel.StubQSTileViewModel import com.android.systemui.res.R import dagger.Binds import dagger.Module import dagger.Provides import dagger.multibindings.IntoMap import dagger.multibindings.StringKey +import javax.inject.Provider @Module interface PolicyModule { - /** Inject DndTile into tileMap in QSModule */ - @Binds @IntoMap @StringKey(DndTile.TILE_SPEC) fun bindDndTile(dndTile: DndTile): QSTileImpl<*> - - /** Inject ModesTile into tileMap in QSModule */ - @Binds - @IntoMap - @StringKey(ModesTile.TILE_SPEC) - fun bindModesTile(modesTile: ModesTile): QSTileImpl<*> - /** Inject WorkModeTile into tileMap in QSModule */ @Binds @IntoMap @@ -136,7 +130,19 @@ interface PolicyModule { const val CAMERA_TOGGLE_TILE_SPEC = "cameratoggle" const val MIC_TOGGLE_TILE_SPEC = "mictoggle" const val DND_TILE_SPEC = "dnd" - const val MODES_TILE_SPEC = "modes" + + /** Inject DndTile or ModesTile into tileMap in QSModule based on feature flag */ + @Provides + @IntoMap + @StringKey(DND_TILE_SPEC) + fun bindDndOrModesTile( + // Using providers to make sure that the unused tile isn't initialised at all if the + // flag is off. + dndTile: Provider<DndTile>, + modesTile: Provider<ModesTile>, + ): QSTileImpl<*> { + return if (android.app.Flags.modesUi()) modesTile.get() else dndTile.get() + } /** Inject flashlight config */ @Provides @@ -283,6 +289,7 @@ interface PolicyModule { labelRes = R.string.quick_settings_work_mode_label, ), instanceId = uiEventLogger.getNewInstanceId(), + autoRemoveOnUnavailable = false, ) /** Inject work mode into tileViewModelMap in QSModule */ @@ -386,51 +393,51 @@ interface PolicyModule { return factory.create(MICROPHONE) } - /** Inject microphone toggle config */ + /** Inject DND tile or Modes tile config based on feature flag */ @Provides @IntoMap @StringKey(DND_TILE_SPEC) - fun provideDndTileConfig(uiEventLogger: QsEventLogger): QSTileConfig = - QSTileConfig( - tileSpec = TileSpec.create(DND_TILE_SPEC), - uiConfig = - QSTileUIConfig.Resource( - iconRes = R.drawable.qs_dnd_icon_off, - labelRes = R.string.quick_settings_dnd_label, - ), - instanceId = uiEventLogger.getNewInstanceId(), - ) - - @Provides - @IntoMap - @StringKey(MODES_TILE_SPEC) - fun provideModesTileConfig(uiEventLogger: QsEventLogger): QSTileConfig = - QSTileConfig( - tileSpec = TileSpec.create(MODES_TILE_SPEC), - uiConfig = - QSTileUIConfig.Resource( - iconRes = R.drawable.qs_dnd_icon_off, - labelRes = R.string.quick_settings_modes_label, - ), - instanceId = uiEventLogger.getNewInstanceId(), - ) + fun provideDndOrModesTileConfig(uiEventLogger: QsEventLogger): QSTileConfig = + if (android.app.Flags.modesUi()) { + QSTileConfig( + tileSpec = TileSpec.create(DND_TILE_SPEC), + uiConfig = + QSTileUIConfig.Resource( + iconRes = R.drawable.qs_dnd_icon_off, + labelRes = R.string.quick_settings_modes_label, + ), + instanceId = uiEventLogger.getNewInstanceId(), + ) + } else { + QSTileConfig( + tileSpec = TileSpec.create(DND_TILE_SPEC), + uiConfig = + QSTileUIConfig.Resource( + iconRes = R.drawable.qs_dnd_icon_off, + labelRes = R.string.quick_settings_dnd_label, + ), + instanceId = uiEventLogger.getNewInstanceId(), + ) + } /** Inject ModesTile into tileViewModelMap in QSModule */ @Provides @IntoMap - @StringKey(MODES_TILE_SPEC) + @StringKey(DND_TILE_SPEC) fun provideModesTileViewModel( factory: QSTileViewModelFactory.Static<ModesTileModel>, mapper: ModesTileMapper, stateInteractor: ModesTileDataInteractor, userActionInteractor: ModesTileUserActionInteractor ): QSTileViewModel = - factory.create( - TileSpec.create(MODES_TILE_SPEC), - userActionInteractor, - stateInteractor, - mapper, - ) + if (android.app.Flags.modesUi() && Flags.qsNewTilesFuture()) + factory.create( + TileSpec.create(DND_TILE_SPEC), + userActionInteractor, + stateInteractor, + mapper, + ) + else StubQSTileViewModel } /** Inject FlashlightTile into tileMap in QSModule */ diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/policy/domain/interactor/ZenModeInteractor.kt b/packages/SystemUI/src/com/android/systemui/statusbar/policy/domain/interactor/ZenModeInteractor.kt index 7a521a6ba28f..efd60f632804 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/policy/domain/interactor/ZenModeInteractor.kt +++ b/packages/SystemUI/src/com/android/systemui/statusbar/policy/domain/interactor/ZenModeInteractor.kt @@ -18,11 +18,15 @@ package com.android.systemui.statusbar.policy.domain.interactor import android.content.Context import android.provider.Settings +import android.provider.Settings.Secure.ZEN_DURATION_FOREVER +import android.provider.Settings.Secure.ZEN_DURATION_PROMPT +import android.util.Log import androidx.concurrent.futures.await import com.android.settingslib.notification.data.repository.ZenModeRepository import com.android.settingslib.notification.modes.ZenIconLoader import com.android.settingslib.notification.modes.ZenMode import com.android.systemui.common.shared.model.Icon +import com.android.systemui.shared.notifications.data.repository.NotificationSettingsRepository import java.time.Duration import javax.inject.Inject import kotlinx.coroutines.flow.Flow @@ -34,11 +38,16 @@ import kotlinx.coroutines.flow.map * An interactor that performs business logic related to the status and configuration of Zen Mode * (or Do Not Disturb/DND Mode). */ -class ZenModeInteractor @Inject constructor(private val repository: ZenModeRepository) { +class ZenModeInteractor +@Inject +constructor( + private val zenModeRepository: ZenModeRepository, + private val notificationSettingsRepository: NotificationSettingsRepository, +) { private val iconLoader: ZenIconLoader = ZenIconLoader.getInstance() val isZenModeEnabled: Flow<Boolean> = - repository.globalZenMode + zenModeRepository.globalZenMode .map { when (it ?: Settings.Global.ZEN_MODE_OFF) { Settings.Global.ZEN_MODE_ALARMS -> true @@ -51,7 +60,9 @@ class ZenModeInteractor @Inject constructor(private val repository: ZenModeRepos .distinctUntilChanged() val areNotificationsHiddenInShade: Flow<Boolean> = - combine(isZenModeEnabled, repository.consolidatedNotificationPolicy) { dndEnabled, policy -> + combine(isZenModeEnabled, zenModeRepository.consolidatedNotificationPolicy) { + dndEnabled, + policy -> if (!dndEnabled) { false } else { @@ -61,17 +72,45 @@ class ZenModeInteractor @Inject constructor(private val repository: ZenModeRepos } .distinctUntilChanged() - val modes: Flow<List<ZenMode>> = repository.modes + val modes: Flow<List<ZenMode>> = zenModeRepository.modes suspend fun getModeIcon(mode: ZenMode, context: Context): Icon { return Icon.Loaded(mode.getIcon(context, iconLoader).await(), contentDescription = null) } - fun activateMode(zenMode: ZenMode, duration: Duration? = null) { - repository.activateMode(zenMode, duration) + fun activateMode(zenMode: ZenMode) { + if (zenMode.isManualDnd) { + val duration = + when (zenDuration) { + ZEN_DURATION_PROMPT -> { + Log.e( + TAG, + "Interactor cannot handle showing the zen duration prompt. " + + "Please use EnableZenModeDialog when this setting is active." + ) + null + } + ZEN_DURATION_FOREVER -> null + else -> Duration.ofMinutes(zenDuration.toLong()) + } + + zenModeRepository.activateMode(zenMode, duration) + } else { + zenModeRepository.activateMode(zenMode) + } } fun deactivateMode(zenMode: ZenMode) { - repository.deactivateMode(zenMode) + zenModeRepository.deactivateMode(zenMode) + } + + private val zenDuration + get() = notificationSettingsRepository.zenDuration.value + + fun shouldAskForZenDuration(mode: ZenMode): Boolean = + mode.isManualDnd && (zenDuration == ZEN_DURATION_PROMPT) + + companion object { + private const val TAG = "ZenModeInteractor" } } diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/policy/ui/dialog/viewmodel/ModeTileViewModel.kt b/packages/SystemUI/src/com/android/systemui/statusbar/policy/ui/dialog/viewmodel/ModeTileViewModel.kt index 5bd26ccc965f..7c1cb6a9b62e 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/policy/ui/dialog/viewmodel/ModeTileViewModel.kt +++ b/packages/SystemUI/src/com/android/systemui/statusbar/policy/ui/dialog/viewmodel/ModeTileViewModel.kt @@ -29,7 +29,6 @@ data class ModeTileViewModel( val text: String, val subtext: String, val enabled: Boolean, - val contentDescription: String, val onClick: () -> Unit, val onLongClick: () -> Unit, ) diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/policy/ui/dialog/viewmodel/ModesDialogViewModel.kt b/packages/SystemUI/src/com/android/systemui/statusbar/policy/ui/dialog/viewmodel/ModesDialogViewModel.kt index c4aa03a3c546..9422878f628b 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/policy/ui/dialog/viewmodel/ModesDialogViewModel.kt +++ b/packages/SystemUI/src/com/android/systemui/statusbar/policy/ui/dialog/viewmodel/ModesDialogViewModel.kt @@ -16,14 +16,18 @@ package com.android.systemui.statusbar.policy.ui.dialog.viewmodel +import android.app.Dialog import android.content.Context import android.content.Intent import android.provider.Settings.ACTION_AUTOMATIC_ZEN_RULE_SETTINGS import android.provider.Settings.EXTRA_AUTOMATIC_ZEN_RULE_ID +import com.android.settingslib.notification.modes.EnableZenModeDialog import com.android.settingslib.notification.modes.ZenMode +import com.android.settingslib.notification.modes.ZenModeDialogMetricsLogger import com.android.systemui.dagger.SysUISingleton import com.android.systemui.dagger.qualifiers.Background import com.android.systemui.res.R +import com.android.systemui.statusbar.phone.SystemUIDialog import com.android.systemui.statusbar.policy.domain.interactor.ZenModeInteractor import com.android.systemui.statusbar.policy.ui.dialog.ModesDialogDelegate import javax.inject.Inject @@ -46,6 +50,8 @@ constructor( @Background val bgDispatcher: CoroutineDispatcher, private val dialogDelegate: ModesDialogDelegate, ) { + private val zenDialogMetricsLogger = ZenModeDialogMetricsLogger(context) + // Modes that should be displayed in the dialog private val visibleModes: Flow<List<ZenMode>> = zenModeInteractor.modes @@ -84,9 +90,6 @@ constructor( text = mode.rule.name, subtext = getTileSubtext(mode), enabled = mode.isActive, - // TODO(b/346519570): This should be some combination of the above, e.g. - // "ON: Do Not Disturb, Until Mon 08:09"; see DndTile. - contentDescription = "", onClick = { if (!mode.rule.isEnabled) { openSettings(mode) @@ -94,8 +97,13 @@ constructor( zenModeInteractor.deactivateMode(mode) } else { if (mode.rule.isManualInvocationAllowed) { - // TODO(b/346519570): Handle duration for DND mode. - zenModeInteractor.activateMode(mode) + if (zenModeInteractor.shouldAskForZenDuration(mode)) { + // NOTE: The dialog handles turning on the mode itself. + val dialog = makeZenModeDialog() + dialog.show() + } else { + zenModeInteractor.activateMode(mode) + } } } }, @@ -125,4 +133,20 @@ constructor( val off = context.resources.getString(R.string.zen_mode_off) return mode.rule.triggerDescription ?: if (mode.isActive) on else off } + + private fun makeZenModeDialog(): Dialog { + val dialog = + EnableZenModeDialog( + context, + R.style.Theme_SystemUI_Dialog, + /* cancelIsNeutral= */ true, + zenDialogMetricsLogger + ) + .createDialog() + SystemUIDialog.applyFlags(dialog) + SystemUIDialog.setShowForAllUsers(dialog, true) + SystemUIDialog.registerDismissListener(dialog) + SystemUIDialog.setDialogSize(dialog) + return dialog + } } diff --git a/packages/SystemUI/src/com/android/systemui/touchpad/TouchpadModule.kt b/packages/SystemUI/src/com/android/systemui/touchpad/TouchpadModule.kt new file mode 100644 index 000000000000..c86ac2f99a13 --- /dev/null +++ b/packages/SystemUI/src/com/android/systemui/touchpad/TouchpadModule.kt @@ -0,0 +1,29 @@ +/* + * Copyright (C) 2024 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.android.systemui.touchpad + +import com.android.systemui.touchpad.data.repository.TouchpadRepository +import com.android.systemui.touchpad.data.repository.TouchpadRepositoryImpl +import dagger.Binds +import dagger.Module + +@Module +abstract class TouchpadModule { + + @Binds + abstract fun bindTouchpadRepository(repository: TouchpadRepositoryImpl): TouchpadRepository +} diff --git a/packages/SystemUI/src/com/android/systemui/touchpad/data/repository/TouchpadRepository.kt b/packages/SystemUI/src/com/android/systemui/touchpad/data/repository/TouchpadRepository.kt new file mode 100644 index 000000000000..7131546ea816 --- /dev/null +++ b/packages/SystemUI/src/com/android/systemui/touchpad/data/repository/TouchpadRepository.kt @@ -0,0 +1,59 @@ +/* + * Copyright (C) 2024 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.android.systemui.touchpad.data.repository + +import android.hardware.input.InputManager +import android.view.InputDevice.SOURCE_TOUCHPAD +import com.android.systemui.dagger.SysUISingleton +import com.android.systemui.dagger.qualifiers.Background +import com.android.systemui.inputdevice.data.repository.InputDeviceRepository +import javax.inject.Inject +import kotlinx.coroutines.CoroutineDispatcher +import kotlinx.coroutines.flow.Flow +import kotlinx.coroutines.flow.distinctUntilChanged +import kotlinx.coroutines.flow.flowOn +import kotlinx.coroutines.flow.map + +interface TouchpadRepository { + /** Emits true if any touchpad is connected to the device, false otherwise. */ + val isAnyTouchpadConnected: Flow<Boolean> +} + +@SysUISingleton +class TouchpadRepositoryImpl +@Inject +constructor( + @Background private val backgroundDispatcher: CoroutineDispatcher, + private val inputManager: InputManager, + inputDeviceRepository: InputDeviceRepository +) : TouchpadRepository { + + override val isAnyTouchpadConnected: Flow<Boolean> = + inputDeviceRepository.deviceChange + .map { (ids, _) -> ids.any { id -> isTouchpad(id) } } + .distinctUntilChanged() + .flowOn(backgroundDispatcher) + + private fun isTouchpad(deviceId: Int): Boolean { + val device = inputManager.getInputDevice(deviceId) ?: return false + return device.supportsSource(SOURCE_TOUCHPAD) + } + + companion object { + const val TAG = "TouchpadRepositoryImpl" + } +} diff --git a/packages/SystemUI/src/com/android/systemui/touchpad/tutorial/ui/composable/BackGestureTutorialScreen.kt b/packages/SystemUI/src/com/android/systemui/touchpad/tutorial/ui/composable/BackGestureTutorialScreen.kt index 94ff65e3b32f..51dfef0b6b6a 100644 --- a/packages/SystemUI/src/com/android/systemui/touchpad/tutorial/ui/composable/BackGestureTutorialScreen.kt +++ b/packages/SystemUI/src/com/android/systemui/touchpad/tutorial/ui/composable/BackGestureTutorialScreen.kt @@ -26,6 +26,7 @@ import androidx.compose.animation.core.LinearEasing import androidx.compose.animation.core.tween import androidx.compose.foundation.layout.Arrangement import androidx.compose.foundation.layout.Box +import androidx.compose.foundation.layout.BoxScope import androidx.compose.foundation.layout.Column import androidx.compose.foundation.layout.Row import androidx.compose.foundation.layout.Spacer @@ -49,6 +50,7 @@ import androidx.compose.ui.input.pointer.pointerInteropFilter import androidx.compose.ui.platform.LocalContext import androidx.compose.ui.res.stringResource import androidx.compose.ui.unit.dp +import com.airbnb.lottie.LottieComposition import com.airbnb.lottie.LottieProperty import com.airbnb.lottie.compose.LottieAnimation import com.airbnb.lottie.compose.LottieCompositionSpec @@ -61,6 +63,9 @@ import com.airbnb.lottie.compose.rememberLottieDynamicProperties import com.airbnb.lottie.compose.rememberLottieDynamicProperty import com.android.compose.theme.LocalAndroidColorScheme import com.android.systemui.res.R +import com.android.systemui.touchpad.tutorial.ui.gesture.GestureState +import com.android.systemui.touchpad.tutorial.ui.gesture.GestureState.FINISHED +import com.android.systemui.touchpad.tutorial.ui.gesture.GestureState.IN_PROGRESS import com.android.systemui.touchpad.tutorial.ui.gesture.TouchpadGesture.BACK import com.android.systemui.touchpad.tutorial.ui.gesture.TouchpadGestureHandler @@ -78,23 +83,49 @@ fun BackGestureTutorialScreen( ) { val screenColors = rememberScreenColors() BackHandler(onBack = onBack) - var gestureDone by remember { mutableStateOf(false) } + var gestureState by remember { mutableStateOf(GestureState.NOT_STARTED) } val swipeDistanceThresholdPx = LocalContext.current.resources.getDimensionPixelSize( com.android.internal.R.dimen.system_gestures_distance_threshold ) val gestureHandler = remember(swipeDistanceThresholdPx) { - TouchpadGestureHandler(BACK, swipeDistanceThresholdPx, onDone = { gestureDone = true }) + TouchpadGestureHandler( + BACK, + swipeDistanceThresholdPx, + onGestureStateChanged = { gestureState = it } + ) } + TouchpadGesturesHandlingBox(gestureHandler, gestureState) { + GestureTutorialContent(gestureState, onDoneButtonClicked, screenColors) + } +} + +@Composable +private fun TouchpadGesturesHandlingBox( + gestureHandler: TouchpadGestureHandler, + gestureState: GestureState, + modifier: Modifier = Modifier, + content: @Composable BoxScope.() -> Unit +) { Box( modifier = - Modifier.fillMaxSize() + modifier + .fillMaxSize() // we need to use pointerInteropFilter because some info about touchpad gestures is // only available in MotionEvent - .pointerInteropFilter(onTouchEvent = gestureHandler::onMotionEvent) + .pointerInteropFilter( + onTouchEvent = { event -> + // FINISHED is the final state so we don't need to process touches anymore + if (gestureState != FINISHED) { + gestureHandler.onMotionEvent(event) + } else { + false + } + } + ) ) { - GestureTutorialContent(gestureDone, onDoneButtonClicked, screenColors) + content() } } @@ -126,14 +157,14 @@ private fun rememberScreenColors(): TutorialScreenColors { @Composable private fun GestureTutorialContent( - gestureDone: Boolean, + gestureState: GestureState, onDoneButtonClicked: () -> Unit, screenColors: TutorialScreenColors ) { val animatedColor by animateColorAsState( targetValue = - if (gestureDone) screenColors.successBackgroundColor + if (gestureState == FINISHED) screenColors.successBackgroundColor else screenColors.backgroundColor, animationSpec = tween(durationMillis = 150, easing = LinearEasing), label = "backgroundColor" @@ -148,15 +179,17 @@ private fun GestureTutorialContent( Row(modifier = Modifier.fillMaxWidth().weight(1f)) { TutorialDescription( titleTextId = - if (gestureDone) R.string.touchpad_tutorial_gesture_done + if (gestureState == FINISHED) R.string.touchpad_tutorial_gesture_done else R.string.touchpad_back_gesture_action_title, titleColor = screenColors.titleColor, - bodyTextId = R.string.touchpad_back_gesture_guidance, + bodyTextId = + if (gestureState == FINISHED) R.string.touchpad_back_gesture_finished + else R.string.touchpad_back_gesture_guidance, modifier = Modifier.weight(1f) ) Spacer(modifier = Modifier.width(76.dp)) TutorialAnimation( - gestureDone, + gestureState, screenColors.animationProperties, modifier = Modifier.weight(1f).padding(top = 8.dp) ) @@ -189,27 +222,38 @@ fun TutorialDescription( @Composable fun TutorialAnimation( - gestureDone: Boolean, + gestureState: GestureState, animationProperties: LottieDynamicProperties, modifier: Modifier = Modifier ) { Column(modifier = modifier.fillMaxWidth()) { - val resId = if (gestureDone) R.raw.trackpad_back_success else R.raw.trackpad_back_edu + val resId = + if (gestureState == FINISHED) R.raw.trackpad_back_success else R.raw.trackpad_back_edu val composition by rememberLottieComposition(LottieCompositionSpec.RawRes(resId)) - val progress by - animateLottieCompositionAsState( - composition, - iterations = if (gestureDone) 1 else LottieConstants.IterateForever - ) + val progress = progressForGestureState(composition, gestureState) LottieAnimation( composition = composition, - progress = { progress }, + progress = progress, dynamicProperties = animationProperties ) } } @Composable +private fun progressForGestureState( + composition: LottieComposition?, + gestureState: GestureState +): () -> Float { + if (gestureState == IN_PROGRESS) { + return { 0f } // when gesture is in progress, animation should freeze on 1st frame + } else { + val iterations = if (gestureState == FINISHED) 1 else LottieConstants.IterateForever + val animationState by animateLottieCompositionAsState(composition, iterations = iterations) + return { animationState } + } +} + +@Composable fun rememberColorFilterProperty( layerName: String, color: Color diff --git a/packages/SystemUI/src/com/android/systemui/touchpad/tutorial/ui/gesture/BackGestureMonitor.kt b/packages/SystemUI/src/com/android/systemui/touchpad/tutorial/ui/gesture/BackGestureMonitor.kt index 1fa7a0c44171..6fa9bcd23045 100644 --- a/packages/SystemUI/src/com/android/systemui/touchpad/tutorial/ui/gesture/BackGestureMonitor.kt +++ b/packages/SystemUI/src/com/android/systemui/touchpad/tutorial/ui/gesture/BackGestureMonitor.kt @@ -17,23 +17,26 @@ package com.android.systemui.touchpad.tutorial.ui.gesture import android.view.MotionEvent +import com.android.systemui.touchpad.tutorial.ui.gesture.GestureState.FINISHED +import com.android.systemui.touchpad.tutorial.ui.gesture.GestureState.IN_PROGRESS +import com.android.systemui.touchpad.tutorial.ui.gesture.GestureState.NOT_STARTED import kotlin.math.abs /** - * Monitor for touchpad gestures that calls [gestureDoneCallback] when gesture was successfully - * done. All tracked motion events should be passed to [processTouchpadEvent] + * Monitor for touchpad gestures that calls [gestureStateChangedCallback] when [GestureState] + * changes. All tracked motion events should be passed to [processTouchpadEvent] */ interface TouchpadGestureMonitor { val gestureDistanceThresholdPx: Int - val gestureDoneCallback: () -> Unit + val gestureStateChangedCallback: (GestureState) -> Unit fun processTouchpadEvent(event: MotionEvent) } class BackGestureMonitor( override val gestureDistanceThresholdPx: Int, - override val gestureDoneCallback: () -> Unit + override val gestureStateChangedCallback: (GestureState) -> Unit ) : TouchpadGestureMonitor { private var xStart = 0f @@ -44,13 +47,16 @@ class BackGestureMonitor( MotionEvent.ACTION_DOWN -> { if (isThreeFingerTouchpadSwipe(event)) { xStart = event.x + gestureStateChangedCallback(IN_PROGRESS) } } MotionEvent.ACTION_UP -> { if (isThreeFingerTouchpadSwipe(event)) { val distance = abs(event.x - xStart) if (distance >= gestureDistanceThresholdPx) { - gestureDoneCallback() + gestureStateChangedCallback(FINISHED) + } else { + gestureStateChangedCallback(NOT_STARTED) } } } diff --git a/core/java/android/app/ICompatCameraControlCallback.aidl b/packages/SystemUI/src/com/android/systemui/touchpad/tutorial/ui/gesture/GestureState.kt index 1a7f21066630..446875af66e7 100644 --- a/core/java/android/app/ICompatCameraControlCallback.aidl +++ b/packages/SystemUI/src/com/android/systemui/touchpad/tutorial/ui/gesture/GestureState.kt @@ -1,5 +1,5 @@ /* - * Copyright (C) 2021 The Android Open Source Project + * Copyright (C) 2024 The Android Open Source Project * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -14,17 +14,10 @@ * limitations under the License. */ -package android.app; +package com.android.systemui.touchpad.tutorial.ui.gesture -/** - * This callback allows ActivityRecord to ask the calling View to apply the treatment for stretched - * issues affecting camera viewfinders when the user clicks on the camera compat control. - * - * {@hide} - */ -oneway interface ICompatCameraControlCallback { - - void applyCameraCompatTreatment(); - - void revertCameraCompatTreatment(); +enum class GestureState { + NOT_STARTED, + IN_PROGRESS, + FINISHED } diff --git a/packages/SystemUI/src/com/android/systemui/touchpad/tutorial/ui/gesture/TouchpadGesture.kt b/packages/SystemUI/src/com/android/systemui/touchpad/tutorial/ui/gesture/TouchpadGesture.kt index 4ae9c7b2426c..190da62aca92 100644 --- a/packages/SystemUI/src/com/android/systemui/touchpad/tutorial/ui/gesture/TouchpadGesture.kt +++ b/packages/SystemUI/src/com/android/systemui/touchpad/tutorial/ui/gesture/TouchpadGesture.kt @@ -22,10 +22,10 @@ enum class TouchpadGesture { fun toMonitor( swipeDistanceThresholdPx: Int, - gestureDoneCallback: () -> Unit + onStateChanged: (GestureState) -> Unit ): TouchpadGestureMonitor { return when (this) { - BACK -> BackGestureMonitor(swipeDistanceThresholdPx, gestureDoneCallback) + BACK -> BackGestureMonitor(swipeDistanceThresholdPx, onStateChanged) else -> throw IllegalArgumentException("Not implemented yet") } } diff --git a/packages/SystemUI/src/com/android/systemui/touchpad/tutorial/ui/gesture/TouchpadGestureHandler.kt b/packages/SystemUI/src/com/android/systemui/touchpad/tutorial/ui/gesture/TouchpadGestureHandler.kt index dc8471c3248a..cac2a99bc02c 100644 --- a/packages/SystemUI/src/com/android/systemui/touchpad/tutorial/ui/gesture/TouchpadGestureHandler.kt +++ b/packages/SystemUI/src/com/android/systemui/touchpad/tutorial/ui/gesture/TouchpadGestureHandler.kt @@ -26,11 +26,11 @@ import android.view.MotionEvent class TouchpadGestureHandler( touchpadGesture: TouchpadGesture, swipeDistanceThresholdPx: Int, - onDone: () -> Unit + onGestureStateChanged: (GestureState) -> Unit ) { private val gestureRecognition = - touchpadGesture.toMonitor(swipeDistanceThresholdPx, gestureDoneCallback = onDone) + touchpadGesture.toMonitor(swipeDistanceThresholdPx, onStateChanged = onGestureStateChanged) fun onMotionEvent(event: MotionEvent): Boolean { // events from touchpad have SOURCE_MOUSE and not SOURCE_TOUCHPAD because of legacy reasons diff --git a/packages/SystemUI/src/com/android/systemui/util/settings/SettingsProxy.kt b/packages/SystemUI/src/com/android/systemui/util/settings/SettingsProxy.kt index b5934ec680d3..9125a915b2a3 100644 --- a/packages/SystemUI/src/com/android/systemui/util/settings/SettingsProxy.kt +++ b/packages/SystemUI/src/com/android/systemui/util/settings/SettingsProxy.kt @@ -336,7 +336,7 @@ interface SettingsProxy { * @param name to look up in the table * @return the corresponding value, or null if not present */ - fun getString(name: String): String + fun getString(name: String): String? /** * Store a name/value pair into the database. @@ -385,15 +385,15 @@ interface SettingsProxy { * an integer. * * @param name The name of the setting to retrieve. - * @param def Value to return if the setting is not defined. - * @return The setting's current value, or 'def' if it is not defined or not a valid integer. + * @param default Value to return if the setting is not defined. + * @return The setting's current value, or default if it is not defined or not a valid integer. */ - fun getInt(name: String, def: Int): Int { + fun getInt(name: String, default: Int): Int { val v = getString(name) return try { - v.toInt() + v?.toInt() ?: default } catch (e: NumberFormatException) { - def + default } } @@ -412,7 +412,7 @@ interface SettingsProxy { */ @Throws(SettingNotFoundException::class) fun getInt(name: String): Int { - val v = getString(name) + val v = getString(name) ?: throw SettingNotFoundException(name) return try { v.toInt() } catch (e: NumberFormatException) { @@ -441,11 +441,11 @@ interface SettingsProxy { * boolean. * * @param name The name of the setting to retrieve. - * @param def Value to return if the setting is not defined. - * @return The setting's current value, or 'def' if it is not defined or not a valid boolean. + * @param default Value to return if the setting is not defined. + * @return The setting's current value, or default if it is not defined or not a valid boolean. */ - fun getBool(name: String, def: Boolean): Boolean { - return getInt(name, if (def) 1 else 0) != 0 + fun getBool(name: String, default: Boolean): Boolean { + return getInt(name, if (default) 1 else 0) != 0 } /** @@ -579,13 +579,12 @@ interface SettingsProxy { companion object { /** Convert a string to a long, or uses a default if the string is malformed or null */ @JvmStatic - fun parseLongOrUseDefault(valString: String, def: Long): Long { - val value: Long - value = + fun parseLongOrUseDefault(valString: String?, default: Long): Long { + val value: Long = try { - valString.toLong() + valString?.toLong() ?: default } catch (e: NumberFormatException) { - def + default } return value } diff --git a/packages/SystemUI/src/com/android/systemui/util/settings/UserSettingsProxy.kt b/packages/SystemUI/src/com/android/systemui/util/settings/UserSettingsProxy.kt index 848a6e691082..ac7c1ce77c9e 100644 --- a/packages/SystemUI/src/com/android/systemui/util/settings/UserSettingsProxy.kt +++ b/packages/SystemUI/src/com/android/systemui/util/settings/UserSettingsProxy.kt @@ -354,12 +354,12 @@ interface UserSettingsProxy : SettingsProxy { * @param name to look up in the table * @return the corresponding value, or null if not present */ - override fun getString(name: String): String { + override fun getString(name: String): String? { return getStringForUser(name, userId) } /** See [getString]. */ - fun getStringForUser(name: String, userHandle: Int): String + fun getStringForUser(name: String, userHandle: Int): String? /** * Store a name/value pair into the database. Values written by this method will be overridden @@ -388,17 +388,17 @@ interface UserSettingsProxy : SettingsProxy { overrideableByRestore: Boolean ): Boolean - override fun getInt(name: String, def: Int): Int { - return getIntForUser(name, def, userId) + override fun getInt(name: String, default: Int): Int { + return getIntForUser(name, default, userId) } /** Similar implementation to [getInt] for the specified [userHandle]. */ - fun getIntForUser(name: String, def: Int, userHandle: Int): Int { + fun getIntForUser(name: String, default: Int, userHandle: Int): Int { val v = getStringForUser(name, userHandle) return try { - v.toInt() + v?.toInt() ?: default } catch (e: NumberFormatException) { - def + default } } @@ -408,7 +408,7 @@ interface UserSettingsProxy : SettingsProxy { /** Similar implementation to [getInt] for the specified [userHandle]. */ @Throws(SettingNotFoundException::class) fun getIntForUser(name: String, userHandle: Int): Int { - val v = getStringForUser(name, userHandle) + val v = getStringForUser(name, userHandle) ?: throw SettingNotFoundException(name) return try { v.toInt() } catch (e: NumberFormatException) { diff --git a/packages/SystemUI/src/com/android/systemui/volume/CsdWarningAction.kt b/packages/SystemUI/src/com/android/systemui/volume/CsdWarningAction.kt new file mode 100644 index 000000000000..a77acb5a3e08 --- /dev/null +++ b/packages/SystemUI/src/com/android/systemui/volume/CsdWarningAction.kt @@ -0,0 +1,48 @@ +/* + * Copyright (C) 2024 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.android.systemui.volume + +import android.app.PendingIntent +import android.app.PendingIntent.FLAG_IMMUTABLE +import android.app.PendingIntent.FLAG_UPDATE_CURRENT +import android.content.Context +import android.content.Intent + +/** + * label: Notification action label text. intent: The Intent used to start Activity or Broadcast. + * isActivity: Defines if the pending intent should start an activity. Default is to broadcast + */ +data class CsdWarningAction( + val label: String? = null, + val intent: Intent? = null, + val isActivity: Boolean = false, +) { + fun toPendingIntent(context: Context): PendingIntent? { + if (label == null || intent == null) { + return null + } + if (isActivity) { + return PendingIntent.getActivity( + context, + 0, + intent, + PendingIntent.FLAG_UPDATE_CURRENT or PendingIntent.FLAG_IMMUTABLE + ) + } + return PendingIntent.getBroadcast(context, 0, intent, FLAG_IMMUTABLE) + } +} diff --git a/packages/SystemUI/src/com/android/systemui/volume/CsdWarningDialog.java b/packages/SystemUI/src/com/android/systemui/volume/CsdWarningDialog.java index bb230e6b0305..a63660ba2804 100644 --- a/packages/SystemUI/src/com/android/systemui/volume/CsdWarningDialog.java +++ b/packages/SystemUI/src/com/android/systemui/volume/CsdWarningDialog.java @@ -30,7 +30,6 @@ import android.content.IntentFilter; import android.media.AudioManager; import android.provider.Settings; import android.util.Log; -import android.util.Pair; import android.view.KeyEvent; import android.view.WindowManager; @@ -109,7 +108,7 @@ public class CsdWarningDialog extends SystemUIDialog private long mShowTime; @VisibleForTesting public int mCachedMediaStreamVolume; - private Optional<ImmutableList<Pair<String, Intent>>> mActionIntents; + private Optional<ImmutableList<CsdWarningAction>> mActionIntents; private final BroadcastDispatcher mBroadcastDispatcher; /** @@ -121,7 +120,7 @@ public class CsdWarningDialog extends SystemUIDialog CsdWarningDialog create( int csdWarning, Runnable onCleanup, - Optional<ImmutableList<Pair<String, Intent>>> actionIntents); + Optional<ImmutableList<CsdWarningAction>> actionIntents); } @AssistedInject @@ -132,7 +131,7 @@ public class CsdWarningDialog extends SystemUIDialog NotificationManager notificationManager, @Background DelayableExecutor delayableExecutor, @Assisted Runnable onCleanup, - @Assisted Optional<ImmutableList<Pair<String, Intent>>> actionIntents, + @Assisted Optional<ImmutableList<CsdWarningAction>> actionIntents, BroadcastDispatcher broadcastDispatcher) { super(context); mCsdWarning = csdWarning; @@ -351,39 +350,45 @@ public class CsdWarningDialog extends SystemUIDialog if (Flags.sounddoseCustomization() && mActionIntents.isPresent() && !mActionIntents.get().isEmpty()) { - ImmutableList<Pair<String, Intent>> actionIntentsList = mActionIntents.get(); - for (Pair<String, Intent> intentPair : actionIntentsList) { - if (intentPair != null && intentPair.first != null && intentPair.second != null) { - PendingIntent pendingActionIntent = - PendingIntent.getBroadcast(mContext, 0, intentPair.second, - FLAG_IMMUTABLE); - builder.addAction(0, intentPair.first, pendingActionIntent); - // Register receiver to undo volume only when - // notification conaining the undo action would be sent. - if (intentPair.first == mContext.getString(R.string.volume_undo_action)) { - final IntentFilter filterUndo = new IntentFilter( - VolumeDialog.ACTION_VOLUME_UNDO); - mBroadcastDispatcher.registerReceiver(mReceiverUndo, - filterUndo, - /* executor = default */ null, - /* user = default */ null, - Context.RECEIVER_NOT_EXPORTED, - /* permission = default */ null); - - // Register receiver to learn if notification has been dismissed. - // This is required to unregister receivers to prevent leak. - Intent dismissIntent = new Intent(DISMISS_CSD_NOTIFICATION) - .setPackage(mContext.getPackageName()); - PendingIntent pendingDismissIntent = PendingIntent.getBroadcast(mContext, - 0, dismissIntent, FLAG_IMMUTABLE); - mBroadcastDispatcher.registerReceiver(mReceiverDismissNotification, - new IntentFilter(DISMISS_CSD_NOTIFICATION), - /* executor = default */ null, - /* user = default */ null, - Context.RECEIVER_NOT_EXPORTED, - /* permission = default */ null); - builder.setDeleteIntent(pendingDismissIntent); - } + ImmutableList<CsdWarningAction> actionIntentsList = mActionIntents.get(); + for (CsdWarningAction action : actionIntentsList) { + if (action.getLabel() == null || action.getIntent() == null) { + Log.w(TAG, "Null action intent received. Skipping addition to notification"); + continue; + } + PendingIntent pendingActionIntent = action.toPendingIntent(mContext); + if (pendingActionIntent == null) { + Log.w(TAG, "Null pending intent received. Skipping addition to notification"); + continue; + } + builder.addAction(0, action.getLabel(), pendingActionIntent); + + // Register receiver to undo volume only when + // notification conaining the undo action would be sent. + if (action.getLabel().equals(mContext.getString(R.string.volume_undo_action))) { + final IntentFilter filterUndo = new IntentFilter( + VolumeDialog.ACTION_VOLUME_UNDO); + mBroadcastDispatcher.registerReceiver(mReceiverUndo, + filterUndo, + /* executor = default */ null, + /* user = default */ null, + Context.RECEIVER_NOT_EXPORTED, + /* permission = default */ null); + + // Register receiver to learn if notification has been dismissed. + // This is required to unregister receivers to prevent leak. + Intent dismissIntent = new Intent(DISMISS_CSD_NOTIFICATION) + .setPackage(mContext.getPackageName()); + PendingIntent pendingDismissIntent = PendingIntent.getBroadcast( + mContext, + 0, dismissIntent, FLAG_IMMUTABLE); + mBroadcastDispatcher.registerReceiver(mReceiverDismissNotification, + new IntentFilter(DISMISS_CSD_NOTIFICATION), + /* executor = default */ null, + /* user = default */ null, + Context.RECEIVER_NOT_EXPORTED, + /* permission = default */ null); + builder.setDeleteIntent(pendingDismissIntent); } } } diff --git a/packages/SystemUI/src/com/android/systemui/volume/VolumeDialogImpl.java b/packages/SystemUI/src/com/android/systemui/volume/VolumeDialogImpl.java index 0770d8926389..e56f6b32c085 100644 --- a/packages/SystemUI/src/com/android/systemui/volume/VolumeDialogImpl.java +++ b/packages/SystemUI/src/com/android/systemui/volume/VolumeDialogImpl.java @@ -51,7 +51,6 @@ import android.app.KeyguardManager; import android.content.ContentResolver; import android.content.Context; import android.content.DialogInterface; -import android.content.Intent; import android.content.pm.PackageManager; import android.content.res.ColorStateList; import android.content.res.Configuration; @@ -79,7 +78,6 @@ import android.provider.Settings; import android.provider.Settings.Global; import android.text.InputFilter; import android.util.Log; -import android.util.Pair; import android.util.Slog; import android.util.SparseBooleanArray; import android.view.ContextThemeWrapper; @@ -322,8 +320,8 @@ public class VolumeDialogImpl implements VolumeDialog, Dumpable, private final VolumePanelFlag mVolumePanelFlag; private final VolumeDialogInteractor mInteractor; // Optional actions for soundDose - private Optional<ImmutableList<Pair<String, Intent>>> mCsdWarningNotificationActions = - Optional.of(ImmutableList.of()); + private Optional<ImmutableList<CsdWarningAction>> + mCsdWarningNotificationActions = Optional.of(ImmutableList.of()); public VolumeDialogImpl( Context context, @@ -2231,7 +2229,7 @@ public class VolumeDialogImpl implements VolumeDialog, Dumpable, } public void setCsdWarningNotificationActionIntents( - ImmutableList<Pair<String, Intent>> actionIntent) { + ImmutableList<CsdWarningAction> actionIntent) { mCsdWarningNotificationActions = Optional.of(actionIntent); } diff --git a/packages/SystemUI/src/com/android/systemui/volume/VolumeUI.java b/packages/SystemUI/src/com/android/systemui/volume/VolumeUI.java index dc2b80c5e391..68d12f69215a 100644 --- a/packages/SystemUI/src/com/android/systemui/volume/VolumeUI.java +++ b/packages/SystemUI/src/com/android/systemui/volume/VolumeUI.java @@ -16,6 +16,8 @@ package com.android.systemui.volume; +import static com.android.settingslib.flags.Flags.volumeDialogAudioSharingFix; + import android.content.Context; import android.content.res.Configuration; import android.os.Handler; @@ -26,6 +28,7 @@ import com.android.systemui.dagger.SysUISingleton; import com.android.systemui.qs.tiles.DndTile; import com.android.systemui.res.R; import com.android.systemui.statusbar.policy.ConfigurationController; +import com.android.systemui.volume.domain.interactor.AudioSharingInteractor; import java.io.PrintWriter; @@ -41,23 +44,29 @@ public class VolumeUI implements CoreStartable, ConfigurationController.Configur private boolean mEnabled; private final Context mContext; private VolumeDialogComponent mVolumeComponent; + private AudioSharingInteractor mAudioSharingInteractor; @Inject - public VolumeUI(Context context, VolumeDialogComponent volumeDialogComponent) { + public VolumeUI(Context context, VolumeDialogComponent volumeDialogComponent, + AudioSharingInteractor audioSharingInteractor) { mContext = context; mVolumeComponent = volumeDialogComponent; + mAudioSharingInteractor = audioSharingInteractor; } @Override public void start() { boolean enableVolumeUi = mContext.getResources().getBoolean(R.bool.enable_volume_ui); boolean enableSafetyWarning = - mContext.getResources().getBoolean(R.bool.enable_safety_warning); + mContext.getResources().getBoolean(R.bool.enable_safety_warning); mEnabled = enableVolumeUi || enableSafetyWarning; if (!mEnabled) return; mVolumeComponent.setEnableDialogs(enableVolumeUi, enableSafetyWarning); setDefaultVolumeController(); + if (volumeDialogAudioSharingFix()) { + mAudioSharingInteractor.handlePrimaryGroupChange(); + } } @Override diff --git a/packages/SystemUI/src/com/android/systemui/volume/dagger/AudioModule.kt b/packages/SystemUI/src/com/android/systemui/volume/dagger/AudioModule.kt index 0c1bc21decfe..efaca7a8239f 100644 --- a/packages/SystemUI/src/com/android/systemui/volume/dagger/AudioModule.kt +++ b/packages/SystemUI/src/com/android/systemui/volume/dagger/AudioModule.kt @@ -75,7 +75,6 @@ interface AudioModule { @Provides @SysUISingleton fun provideAudioSharingRepository( - @Application context: Context, contentResolver: ContentResolver, localBluetoothManager: LocalBluetoothManager?, @Application coroutineScope: CoroutineScope, diff --git a/packages/SystemUI/src/com/android/systemui/volume/domain/interactor/AudioSharingInteractor.kt b/packages/SystemUI/src/com/android/systemui/volume/domain/interactor/AudioSharingInteractor.kt index aba3015a6b7d..2170c36ec019 100644 --- a/packages/SystemUI/src/com/android/systemui/volume/domain/interactor/AudioSharingInteractor.kt +++ b/packages/SystemUI/src/com/android/systemui/volume/domain/interactor/AudioSharingInteractor.kt @@ -17,18 +17,28 @@ package com.android.systemui.volume.domain.interactor import android.bluetooth.BluetoothCsipSetCoordinator +import android.media.AudioManager.STREAM_MUSIC import androidx.annotation.IntRange import com.android.settingslib.volume.data.repository.AudioSharingRepository import com.android.settingslib.volume.data.repository.AudioSharingRepository.Companion.AUDIO_SHARING_VOLUME_MAX import com.android.settingslib.volume.data.repository.AudioSharingRepository.Companion.AUDIO_SHARING_VOLUME_MIN +import com.android.settingslib.volume.domain.interactor.AudioVolumeInteractor +import com.android.settingslib.volume.shared.model.AudioStream import com.android.systemui.dagger.SysUISingleton import com.android.systemui.dagger.qualifiers.Application +import com.android.systemui.dagger.qualifiers.Background import javax.inject.Inject +import kotlin.coroutines.CoroutineContext import kotlinx.coroutines.CoroutineScope import kotlinx.coroutines.flow.Flow import kotlinx.coroutines.flow.combine +import kotlinx.coroutines.flow.distinctUntilChanged import kotlinx.coroutines.flow.emptyFlow +import kotlinx.coroutines.flow.filterNotNull +import kotlinx.coroutines.flow.first +import kotlinx.coroutines.flow.map import kotlinx.coroutines.launch +import kotlinx.coroutines.withContext interface AudioSharingInteractor { /** Audio sharing secondary headset volume changes. */ @@ -45,6 +55,16 @@ interface AudioSharingInteractor { @IntRange(from = AUDIO_SHARING_VOLUME_MIN.toLong(), to = AUDIO_SHARING_VOLUME_MAX.toLong()) level: Int ) + + /** + * Handle primary group change in audio sharing. + * + * Once the primary group is changed, we need to sync its volume to STREAM_MUSIC to make sure + * the volume adjustment during audio sharing can be kept after the sharing ends. + * + * TODO(b/355396988) Migrate to audio framework solution once it is in place. + */ + fun handlePrimaryGroupChange() } @SysUISingleton @@ -52,26 +72,60 @@ class AudioSharingInteractorImpl @Inject constructor( @Application private val coroutineScope: CoroutineScope, + @Background private val backgroundCoroutineContext: CoroutineContext, + private val audioVolumeInteractor: AudioVolumeInteractor, private val audioSharingRepository: AudioSharingRepository ) : AudioSharingInteractor { override val volume: Flow<Int?> = combine(audioSharingRepository.secondaryGroupId, audioSharingRepository.volumeMap) { - secondaryGroupId, - volumeMap -> - if (secondaryGroupId == BluetoothCsipSetCoordinator.GROUP_ID_INVALID) null - else volumeMap.getOrDefault(secondaryGroupId, DEFAULT_VOLUME) - } + secondaryGroupId, + volumeMap -> + if (secondaryGroupId == BluetoothCsipSetCoordinator.GROUP_ID_INVALID) null + else volumeMap.getOrDefault(secondaryGroupId, DEFAULT_VOLUME) + } + .distinctUntilChanged() override val volumeMin: Int = AUDIO_SHARING_VOLUME_MIN override val volumeMax: Int = AUDIO_SHARING_VOLUME_MAX - override fun setStreamVolume(level: Int) { + override fun setStreamVolume( + @IntRange(from = AUDIO_SHARING_VOLUME_MIN.toLong(), to = AUDIO_SHARING_VOLUME_MAX.toLong()) + level: Int + ) { coroutineScope.launch { audioSharingRepository.setSecondaryVolume(level) } } + override fun handlePrimaryGroupChange() { + coroutineScope.launch { + audioSharingRepository.primaryGroupId + .map { primaryGroupId -> audioSharingRepository.volumeMap.value[primaryGroupId] } + .filterNotNull() + .distinctUntilChanged() + .collect { + // Once primary device change, we need to update the STREAM_MUSIC volume to get + // align with the primary device's volume + setMusicStreamVolume(it) + } + } + } + + private suspend fun setMusicStreamVolume(volume: Int) { + withContext(backgroundCoroutineContext) { + val musicStream = + audioVolumeInteractor.getAudioStream(AudioStream(STREAM_MUSIC)).first() + val musicVolume = + Math.round( + volume.toFloat() * (musicStream.maxVolume - musicStream.minVolume) / + (AUDIO_SHARING_VOLUME_MAX - AUDIO_SHARING_VOLUME_MIN) + ) + audioVolumeInteractor.setVolume(AudioStream(STREAM_MUSIC), musicVolume) + } + } + private companion object { + const val TAG = "AudioSharingInteractor" const val DEFAULT_VOLUME = 20 } } @@ -82,7 +136,12 @@ class AudioSharingInteractorEmptyImpl @Inject constructor() : AudioSharingIntera override val volumeMin: Int = EMPTY_VOLUME override val volumeMax: Int = EMPTY_VOLUME - override fun setStreamVolume(level: Int) {} + override fun setStreamVolume( + @IntRange(from = AUDIO_SHARING_VOLUME_MIN.toLong(), to = AUDIO_SHARING_VOLUME_MAX.toLong()) + level: Int + ) {} + + override fun handlePrimaryGroupChange() {} private companion object { const val EMPTY_VOLUME = 0 diff --git a/packages/SystemUI/tests/src/com/android/systemui/accessibility/FullscreenMagnificationControllerTest.java b/packages/SystemUI/tests/src/com/android/systemui/accessibility/FullscreenMagnificationControllerTest.java index cbd535ba7c2b..530ae158cf43 100644 --- a/packages/SystemUI/tests/src/com/android/systemui/accessibility/FullscreenMagnificationControllerTest.java +++ b/packages/SystemUI/tests/src/com/android/systemui/accessibility/FullscreenMagnificationControllerTest.java @@ -25,6 +25,7 @@ import static com.google.common.truth.Truth.assertWithMessage; import static org.mockito.ArgumentMatchers.any; import static org.mockito.ArgumentMatchers.eq; +import static org.mockito.Mockito.mock; import static org.mockito.Mockito.spy; import static org.mockito.Mockito.verify; import static org.mockito.Mockito.when; @@ -36,7 +37,10 @@ import android.animation.ValueAnimator; import android.content.Context; import android.content.pm.ActivityInfo; import android.graphics.Rect; +import android.graphics.drawable.GradientDrawable; +import android.hardware.display.DisplayManager; import android.os.RemoteException; +import android.platform.test.annotations.EnableFlags; import android.testing.AndroidTestingRunner; import android.testing.TestableLooper; import android.view.Display; @@ -54,6 +58,7 @@ import android.window.InputTransferToken; import androidx.annotation.NonNull; import androidx.test.filters.SmallTest; +import com.android.systemui.Flags; import com.android.systemui.SysuiTestCase; import com.android.systemui.res.R; @@ -61,6 +66,7 @@ import org.junit.After; import org.junit.Before; import org.junit.Test; import org.junit.runner.RunWith; +import org.mockito.ArgumentCaptor; import org.mockito.Mock; import org.mockito.MockitoAnnotations; @@ -76,6 +82,12 @@ public class FullscreenMagnificationControllerTest extends SysuiTestCase { private static final long WAIT_TIMEOUT_S = 5L * HW_TIMEOUT_MULTIPLIER; private static final long ANIMATION_TIMEOUT_MS = 5L * ANIMATION_DURATION_MS * HW_TIMEOUT_MULTIPLIER; + + private static final String UNIQUE_DISPLAY_ID_PRIMARY = "000"; + private static final String UNIQUE_DISPLAY_ID_SECONDARY = "111"; + private static final int CORNER_RADIUS_PRIMARY = 10; + private static final int CORNER_RADIUS_SECONDARY = 20; + private FullscreenMagnificationController mFullscreenMagnificationController; private SurfaceControlViewHost mSurfaceControlViewHost; private ValueAnimator mShowHideBorderAnimator; @@ -83,10 +95,35 @@ public class FullscreenMagnificationControllerTest extends SysuiTestCase { private TestableWindowManager mWindowManager; @Mock private IWindowManager mIWindowManager; + @Mock + private DisplayManager mDisplayManager; @Before public void setUp() { MockitoAnnotations.initMocks(this); + mContext = spy(mContext); + Display display = mock(Display.class); + when(display.getUniqueId()).thenReturn(UNIQUE_DISPLAY_ID_PRIMARY); + when(mContext.getDisplayNoVerify()).thenReturn(display); + + // Override the resources to Display Primary + mContext.getOrCreateTestableResources() + .addOverride( + com.android.internal.R.dimen.rounded_corner_radius, + CORNER_RADIUS_PRIMARY); + mContext.getOrCreateTestableResources() + .addOverride(com.android.internal.R.dimen.rounded_corner_radius_adjustment, 0); + mContext.getOrCreateTestableResources() + .addOverride(com.android.internal.R.dimen.rounded_corner_radius_top, 0); + mContext.getOrCreateTestableResources() + .addOverride( + com.android.internal.R.dimen.rounded_corner_radius_top_adjustment, 0); + mContext.getOrCreateTestableResources() + .addOverride(com.android.internal.R.dimen.rounded_corner_radius_bottom, 0); + mContext.getOrCreateTestableResources() + .addOverride( + com.android.internal.R.dimen.rounded_corner_radius_bottom_adjustment, 0); + getInstrumentation().runOnMainSync(() -> mSurfaceControlViewHost = spy(new SurfaceControlViewHost(mContext, mContext.getDisplay(), new InputTransferToken(), "FullscreenMagnification"))); @@ -101,6 +138,7 @@ public class FullscreenMagnificationControllerTest extends SysuiTestCase { mContext, mContext.getMainThreadHandler(), mContext.getMainExecutor(), + mDisplayManager, mContext.getSystemService(AccessibilityManager.class), mContext.getSystemService(WindowManager.class), mIWindowManager, @@ -259,6 +297,87 @@ public class FullscreenMagnificationControllerTest extends SysuiTestCase { verify(mSurfaceControlViewHost).relayout(newWidth, newHeight); } + @EnableFlags(Flags.FLAG_UPDATE_CORNER_RADIUS_ON_DISPLAY_CHANGED) + @Test + public void enableFullscreenMagnification_applyPrimaryCornerRadius() + throws InterruptedException { + CountDownLatch transactionCommittedLatch = new CountDownLatch(1); + CountDownLatch animationEndLatch = new CountDownLatch(1); + mTransaction.addTransactionCommittedListener( + Runnable::run, transactionCommittedLatch::countDown); + mShowHideBorderAnimator.addListener(new AnimatorListenerAdapter() { + @Override + public void onAnimationEnd(Animator animation) { + animationEndLatch.countDown(); + } + }); + + getInstrumentation().runOnMainSync(() -> + //Enable fullscreen magnification + mFullscreenMagnificationController + .onFullscreenMagnificationActivationChanged(true)); + assertWithMessage("Failed to wait for transaction committed") + .that(transactionCommittedLatch.await(WAIT_TIMEOUT_S, TimeUnit.SECONDS)) + .isTrue(); + assertWithMessage("Failed to wait for animation to be finished") + .that(animationEndLatch.await(ANIMATION_TIMEOUT_MS, TimeUnit.MILLISECONDS)) + .isTrue(); + + // Verify the initial corner radius is applied + GradientDrawable backgroundDrawable = + (GradientDrawable) mSurfaceControlViewHost.getView().getBackground(); + assertThat(backgroundDrawable.getCornerRadius()).isEqualTo(CORNER_RADIUS_PRIMARY); + } + + @EnableFlags(Flags.FLAG_UPDATE_CORNER_RADIUS_ON_DISPLAY_CHANGED) + @Test + public void onDisplayChanged_updateCornerRadiusToSecondary() throws InterruptedException { + CountDownLatch transactionCommittedLatch = new CountDownLatch(1); + CountDownLatch animationEndLatch = new CountDownLatch(1); + mTransaction.addTransactionCommittedListener( + Runnable::run, transactionCommittedLatch::countDown); + mShowHideBorderAnimator.addListener(new AnimatorListenerAdapter() { + @Override + public void onAnimationEnd(Animator animation) { + animationEndLatch.countDown(); + } + }); + + getInstrumentation().runOnMainSync(() -> + //Enable fullscreen magnification + mFullscreenMagnificationController + .onFullscreenMagnificationActivationChanged(true)); + assertWithMessage("Failed to wait for transaction committed") + .that(transactionCommittedLatch.await(WAIT_TIMEOUT_S, TimeUnit.SECONDS)) + .isTrue(); + assertWithMessage("Failed to wait for animation to be finished") + .that(animationEndLatch.await(ANIMATION_TIMEOUT_MS, TimeUnit.MILLISECONDS)) + .isTrue(); + + ArgumentCaptor<DisplayManager.DisplayListener> displayListenerCaptor = + ArgumentCaptor.forClass(DisplayManager.DisplayListener.class); + verify(mDisplayManager).registerDisplayListener(displayListenerCaptor.capture(), any()); + + Display newDisplay = mock(Display.class); + when(newDisplay.getUniqueId()).thenReturn(UNIQUE_DISPLAY_ID_SECONDARY); + when(mContext.getDisplayNoVerify()).thenReturn(newDisplay); + // Override the resources to Display Secondary + mContext.getOrCreateTestableResources() + .removeOverride(com.android.internal.R.dimen.rounded_corner_radius); + mContext.getOrCreateTestableResources() + .addOverride( + com.android.internal.R.dimen.rounded_corner_radius, + CORNER_RADIUS_SECONDARY); + getInstrumentation().runOnMainSync(() -> + displayListenerCaptor.getValue().onDisplayChanged(Display.DEFAULT_DISPLAY)); + waitForIdleSync(); + // Verify the corner radius is updated + GradientDrawable backgroundDrawable2 = + (GradientDrawable) mSurfaceControlViewHost.getView().getBackground(); + assertThat(backgroundDrawable2.getCornerRadius()).isEqualTo(CORNER_RADIUS_SECONDARY); + } + + private ValueAnimator newNullTargetObjectAnimator() { final ValueAnimator animator = ObjectAnimator.ofFloat(/* target= */ null, View.ALPHA, 0f, 1f); diff --git a/packages/SystemUI/tests/src/com/android/systemui/accessibility/extradim/ExtraDimDialogDelegateTest.kt b/packages/SystemUI/tests/src/com/android/systemui/accessibility/extradim/ExtraDimDialogDelegateTest.kt new file mode 100644 index 000000000000..b80836d80e12 --- /dev/null +++ b/packages/SystemUI/tests/src/com/android/systemui/accessibility/extradim/ExtraDimDialogDelegateTest.kt @@ -0,0 +1,118 @@ +/* + * Copyright (C) 2024 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package com.android.systemui.accessibility.extradim + +import android.content.DialogInterface +import android.testing.TestableLooper +import android.view.accessibility.AccessibilityManager +import androidx.test.ext.junit.runners.AndroidJUnit4 +import androidx.test.filters.SmallTest +import com.android.internal.accessibility.AccessibilityShortcutController +import com.android.internal.accessibility.common.ShortcutConstants +import com.android.systemui.SysuiTestCase +import com.android.systemui.kosmos.Kosmos +import com.android.systemui.kosmos.testCase +import com.android.systemui.kosmos.testDispatcher +import com.android.systemui.kosmos.testScope +import com.android.systemui.model.SysUiState +import com.android.systemui.res.R +import com.android.systemui.settings.UserTracker +import com.android.systemui.statusbar.phone.SystemUIDialog +import kotlinx.coroutines.ExperimentalCoroutinesApi +import kotlinx.coroutines.test.advanceUntilIdle +import kotlinx.coroutines.test.runCurrent +import kotlinx.coroutines.test.runTest +import org.junit.Before +import org.junit.Rule +import org.junit.Test +import org.junit.runner.RunWith +import org.mockito.ArgumentMatchers.anyBoolean +import org.mockito.ArgumentMatchers.anyInt +import org.mockito.ArgumentMatchers.anyLong +import org.mockito.Mock +import org.mockito.Mockito.`when` as whenever +import org.mockito.junit.MockitoJUnit +import org.mockito.junit.MockitoRule +import org.mockito.kotlin.argumentCaptor +import org.mockito.kotlin.eq +import org.mockito.kotlin.verify + +/** Tests for [ExtraDimDialogDelegate]. */ +@OptIn(ExperimentalCoroutinesApi::class) +@SmallTest +@TestableLooper.RunWithLooper(setAsMainLooper = true) +@RunWith(AndroidJUnit4::class) +class ExtraDimDialogDelegateTest : SysuiTestCase() { + @get:Rule val mockitoRule: MockitoRule = MockitoJUnit.rule() + + private lateinit var extraDimDialogDelegate: ExtraDimDialogDelegate + + private val kosmos = Kosmos().also { it.testCase = this } + private val testScope = kosmos.testScope + + @Mock private lateinit var dialog: SystemUIDialog + @Mock private lateinit var accessibilityManager: AccessibilityManager + @Mock private lateinit var dialogFactory: SystemUIDialog.Factory + @Mock private lateinit var userTracker: UserTracker + @Mock private lateinit var sysuiState: SysUiState + + @Before + fun setUp() { + whenever(sysuiState.setFlag(anyLong(), anyBoolean())).thenReturn(sysuiState) + whenever(dialog.context).thenReturn(context) + + extraDimDialogDelegate = + ExtraDimDialogDelegate( + context, + testScope.backgroundScope, + kosmos.testDispatcher, + dialogFactory, + accessibilityManager, + userTracker + ) + } + + @Test + fun clickButton_removeExtraDimShortcuts() = + kosmos.testScope.runTest { + extraDimDialogDelegate.beforeCreate(dialog, /* savedInstanceState= */ null) + + val clickListener = argumentCaptor<DialogInterface.OnClickListener>() + + // Verify the button has the right text + verify(dialog) + .setPositiveButton( + eq(R.string.accessibility_deprecate_extra_dim_dialog_button), + clickListener.capture() + ) + + clickListener.firstValue.onClick(dialog, 0) + advanceUntilIdle() + runCurrent() + verify(accessibilityManager) + .enableShortcutsForTargets( + eq(false), + eq(ShortcutConstants.UserShortcutType.ALL), + eq( + setOf( + AccessibilityShortcutController.REDUCE_BRIGHT_COLORS_COMPONENT_NAME + .flattenToString() + ) + ), + anyInt() + ) + } +} diff --git a/packages/SystemUI/tests/src/com/android/systemui/accessibility/extradim/ExtraDimDialogManagerTest.kt b/packages/SystemUI/tests/src/com/android/systemui/accessibility/extradim/ExtraDimDialogManagerTest.kt new file mode 100644 index 000000000000..1386092ef93e --- /dev/null +++ b/packages/SystemUI/tests/src/com/android/systemui/accessibility/extradim/ExtraDimDialogManagerTest.kt @@ -0,0 +1,62 @@ +/* + * Copyright (C) 2024 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package com.android.systemui.accessibility.extradim + +import androidx.test.ext.junit.runners.AndroidJUnit4 +import androidx.test.filters.SmallTest +import com.android.systemui.SysuiTestCase +import com.android.systemui.plugins.ActivityStarter +import javax.inject.Provider +import org.junit.Before +import org.junit.Rule +import org.junit.Test +import org.junit.runner.RunWith +import org.mockito.ArgumentMatchers.any +import org.mockito.ArgumentMatchers.eq +import org.mockito.Mock +import org.mockito.junit.MockitoJUnit +import org.mockito.junit.MockitoRule +import org.mockito.kotlin.verify + +/** Tests for [ExtraDimDialogManager]. */ +@SmallTest +@RunWith(AndroidJUnit4::class) +class ExtraDimDialogManagerTest : SysuiTestCase() { + @get:Rule val mockitoRule: MockitoRule = MockitoJUnit.rule() + + private lateinit var extraDimDialogManager: ExtraDimDialogManager + + @Mock private lateinit var activityStarter: ActivityStarter + @Mock private lateinit var dialogProvider: Provider<ExtraDimDialogDelegate> + + @Before + fun setUp() { + extraDimDialogManager = ExtraDimDialogManager(dialogProvider, activityStarter) + } + + @Test + fun dismissKeyguardIfNeededAndShowDialog_executeRunnableDismissingKeyguard() { + extraDimDialogManager.dismissKeyguardIfNeededAndShowDialog() + verify(activityStarter) + .executeRunnableDismissingKeyguard( + any(), + /* cancelAction= */ eq(null), + /* dismissShade= */ eq(false), + /* afterKeyguardGone= */ eq(true), + /* deferred= */ eq(false) + ) + } +} diff --git a/packages/SystemUI/tests/src/com/android/systemui/accessibility/extradim/ExtraDimDialogReceiverTest.kt b/packages/SystemUI/tests/src/com/android/systemui/accessibility/extradim/ExtraDimDialogReceiverTest.kt new file mode 100644 index 000000000000..ebe7500300c8 --- /dev/null +++ b/packages/SystemUI/tests/src/com/android/systemui/accessibility/extradim/ExtraDimDialogReceiverTest.kt @@ -0,0 +1,66 @@ +/* + * Copyright (C) 2024 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package com.android.systemui.accessibility.extradim + +import android.content.Intent +import android.platform.test.annotations.DisableFlags +import android.platform.test.annotations.EnableFlags +import androidx.test.ext.junit.runners.AndroidJUnit4 +import androidx.test.filters.SmallTest +import com.android.server.display.feature.flags.Flags +import com.android.systemui.SysuiTestCase +import org.junit.Before +import org.junit.Rule +import org.junit.Test +import org.junit.runner.RunWith +import org.mockito.Mock +import org.mockito.junit.MockitoJUnit +import org.mockito.junit.MockitoRule +import org.mockito.kotlin.never +import org.mockito.kotlin.verify + +/** Tests for [ExtraDimDialogReceiver]. */ +@SmallTest +@RunWith(AndroidJUnit4::class) +class ExtraDimDialogReceiverTest : SysuiTestCase() { + @get:Rule val mockitoRule: MockitoRule = MockitoJUnit.rule() + + private lateinit var extraDimDialogReceiver: ExtraDimDialogReceiver + + @Mock private lateinit var extraDimDialogManager: ExtraDimDialogManager + + @Before + fun setUp() { + extraDimDialogReceiver = ExtraDimDialogReceiver(extraDimDialogManager) + mContext + .getOrCreateTestableResources() + .addOverride(com.android.internal.R.bool.config_evenDimmerEnabled, true) + } + + @Test + @EnableFlags(Flags.FLAG_EVEN_DIMMER) + fun receiveAction_flagEvenDimmerEnabled_showDialog() { + extraDimDialogReceiver.onReceive(mContext, Intent(ExtraDimDialogReceiver.ACTION)) + verify(extraDimDialogManager).dismissKeyguardIfNeededAndShowDialog() + } + + @Test + @DisableFlags(Flags.FLAG_EVEN_DIMMER) + fun receiveAction_flagEvenDimmerDisabled_neverShowDialog() { + extraDimDialogReceiver.onReceive(mContext, Intent(ExtraDimDialogReceiver.ACTION)) + verify(extraDimDialogManager, never()).dismissKeyguardIfNeededAndShowDialog() + } +} diff --git a/packages/SystemUI/tests/src/com/android/systemui/accessibility/hearingaid/HearingDevicesDialogDelegateTest.java b/packages/SystemUI/tests/src/com/android/systemui/accessibility/hearingaid/HearingDevicesDialogDelegateTest.java index 5ea5c2189560..d3b7d2207854 100644 --- a/packages/SystemUI/tests/src/com/android/systemui/accessibility/hearingaid/HearingDevicesDialogDelegateTest.java +++ b/packages/SystemUI/tests/src/com/android/systemui/accessibility/hearingaid/HearingDevicesDialogDelegateTest.java @@ -52,6 +52,7 @@ import android.widget.Spinner; import androidx.test.ext.junit.runners.AndroidJUnit4; import androidx.test.filters.SmallTest; +import com.android.internal.logging.UiEventLogger; import com.android.settingslib.bluetooth.BluetoothEventManager; import com.android.settingslib.bluetooth.CachedBluetoothDevice; import com.android.settingslib.bluetooth.CachedBluetoothDeviceManager; @@ -123,6 +124,8 @@ public class HearingDevicesDialogDelegateTest extends SysuiTestCase { @Mock private AudioManager mAudioManager; @Mock + private UiEventLogger mUiEventLogger; + @Mock private CachedBluetoothDevice mCachedDevice; @Mock private BluetoothDevice mDevice; @@ -179,6 +182,7 @@ public class HearingDevicesDialogDelegateTest extends SysuiTestCase { anyInt(), any()); assertThat(intentCaptor.getValue().getAction()).isEqualTo( Settings.ACTION_HEARING_DEVICE_PAIRING_SETTINGS); + verify(mUiEventLogger).log(HearingDevicesUiEvent.HEARING_DEVICES_PAIR); } @Test @@ -192,7 +196,7 @@ public class HearingDevicesDialogDelegateTest extends SysuiTestCase { anyInt(), any()); assertThat(intentCaptor.getValue().getAction()).isEqualTo( HearingDevicesDialogDelegate.ACTION_BLUETOOTH_DEVICE_DETAILS); - + verify(mUiEventLogger).log(HearingDevicesUiEvent.HEARING_DEVICES_GEAR_CLICK); } @Test @@ -200,9 +204,10 @@ public class HearingDevicesDialogDelegateTest extends SysuiTestCase { setUpDeviceListDialog(); when(mHearingDeviceItem.getType()).thenReturn(DeviceItemType.CONNECTED_BLUETOOTH_DEVICE); - mDialogDelegate.onDeviceItemOnClicked(mHearingDeviceItem, new View(mContext)); + mDialogDelegate.onDeviceItemClicked(mHearingDeviceItem, new View(mContext)); verify(mCachedDevice).disconnect(); + verify(mUiEventLogger).log(HearingDevicesUiEvent.HEARING_DEVICES_DISCONNECT); } @Test @@ -304,7 +309,8 @@ public class HearingDevicesDialogDelegateTest extends SysuiTestCase { mDialogTransitionAnimator, mLocalBluetoothManager, new Handler(mTestableLooper.getLooper()), - mAudioManager + mAudioManager, + mUiEventLogger ); mDialog = mDialogDelegate.createDialog(); @@ -326,7 +332,8 @@ public class HearingDevicesDialogDelegateTest extends SysuiTestCase { mDialogTransitionAnimator, mLocalBluetoothManager, new Handler(mTestableLooper.getLooper()), - mAudioManager + mAudioManager, + mUiEventLogger ); mDialog = mDialogDelegate.createDialog(); diff --git a/packages/SystemUI/tests/src/com/android/systemui/biometrics/ui/viewmodel/PromptViewModelTest.kt b/packages/SystemUI/tests/src/com/android/systemui/biometrics/ui/viewmodel/PromptViewModelTest.kt index 9df653f1550b..e603db417785 100644 --- a/packages/SystemUI/tests/src/com/android/systemui/biometrics/ui/viewmodel/PromptViewModelTest.kt +++ b/packages/SystemUI/tests/src/com/android/systemui/biometrics/ui/viewmodel/PromptViewModelTest.kt @@ -491,7 +491,7 @@ internal class PromptViewModelTest(private val testCase: TestCase) : SysuiTestCa assertThat(iconAsset) .isEqualTo(R.raw.fingerprint_dialogue_error_to_unlock_lottie) assertThat(iconContentDescriptionId) - .isEqualTo(R.string.fingerprint_dialog_authenticated_confirmation) + .isEqualTo(R.string.biometric_dialog_confirm) assertThat(shouldAnimateIconView).isEqualTo(true) // Confirm authentication @@ -601,7 +601,7 @@ internal class PromptViewModelTest(private val testCase: TestCase) : SysuiTestCa .isEqualTo(R.raw.fingerprint_dialogue_fingerprint_to_unlock_lottie) assertThat(iconOverlayAsset).isEqualTo(-1) assertThat(iconContentDescriptionId) - .isEqualTo(R.string.fingerprint_dialog_authenticated_confirmation) + .isEqualTo(R.string.biometric_dialog_confirm) assertThat(shouldAnimateIconView).isEqualTo(true) assertThat(shouldAnimateIconOverlay).isEqualTo(false) } diff --git a/packages/SystemUI/tests/src/com/android/systemui/doze/DozeScreenBrightnessTest.java b/packages/SystemUI/tests/src/com/android/systemui/doze/DozeScreenBrightnessTest.java index aa5edae72684..4818119045a5 100644 --- a/packages/SystemUI/tests/src/com/android/systemui/doze/DozeScreenBrightnessTest.java +++ b/packages/SystemUI/tests/src/com/android/systemui/doze/DozeScreenBrightnessTest.java @@ -42,13 +42,21 @@ import static org.mockito.Mockito.verify; import static org.mockito.Mockito.when; import android.content.Intent; +import android.hardware.display.DisplayManager; import android.os.PowerManager; import android.os.UserHandle; +import android.platform.test.annotations.RequiresFlagsDisabled; +import android.platform.test.annotations.RequiresFlagsEnabled; +import android.platform.test.flag.junit.CheckFlagsRule; +import android.platform.test.flag.junit.DeviceFlagsValueProvider; import android.provider.Settings; +import android.view.Display; import androidx.test.ext.junit.runners.AndroidJUnit4; import androidx.test.filters.SmallTest; +import com.android.internal.display.BrightnessSynchronizer; +import com.android.server.display.feature.flags.Flags; import com.android.systemui.SysuiTestCase; import com.android.systemui.dock.DockManager; import com.android.systemui.keyguard.WakefulnessLifecycle; @@ -62,6 +70,7 @@ import com.android.systemui.util.settings.SystemSettings; import com.android.systemui.util.time.FakeSystemClock; import org.junit.Before; +import org.junit.Rule; import org.junit.Test; import org.junit.runner.RunWith; import org.mockito.ArgumentCaptor; @@ -74,10 +83,15 @@ import java.util.Optional; @RunWith(AndroidJUnit4.class) public class DozeScreenBrightnessTest extends SysuiTestCase { - private static final int DEFAULT_BRIGHTNESS = 10; - private static final int DIM_BRIGHTNESS = 1; - private static final int[] SENSOR_TO_BRIGHTNESS = new int[]{-1, 1, 2, 3, 4}; + private static final int DEFAULT_BRIGHTNESS_INT = 10; + private static final float DEFAULT_BRIGHTNESS_FLOAT = 0.1f; + private static final int DIM_BRIGHTNESS_INT = 1; + private static final float DIM_BRIGHTNESS_FLOAT = 0.05f; + private static final int[] SENSOR_TO_BRIGHTNESS_INT = new int[]{-1, 1, 2, 3, 4}; + private static final float[] SENSOR_TO_BRIGHTNESS_FLOAT = + new float[]{-1, 0.01f, 0.05f, 0.7f, 0.1f}; private static final int[] SENSOR_TO_OPACITY = new int[]{-1, 10, 0, 0, 0}; + private static final float DELTA = BrightnessSynchronizer.EPSILON; private DozeServiceFake mServiceFake; private FakeSensorManager.FakeGenericSensor mSensor; @@ -98,16 +112,23 @@ public class DozeScreenBrightnessTest extends SysuiTestCase { DozeLog mDozeLog; @Mock SystemSettings mSystemSettings; + @Mock + DisplayManager mDisplayManager; private FakeExecutor mFakeExecutor = new FakeExecutor(new FakeSystemClock()); private FakeThreadFactory mFakeThreadFactory = new FakeThreadFactory(mFakeExecutor); private DozeScreenBrightness mScreen; + @Rule + public final CheckFlagsRule mCheckFlagsRule = DeviceFlagsValueProvider.createCheckFlagsRule(); + @Before public void setUp() throws Exception { MockitoAnnotations.initMocks(this); when(mSystemSettings.getIntForUser(eq(Settings.System.SCREEN_BRIGHTNESS), anyInt(), - eq(UserHandle.USER_CURRENT))).thenReturn(DEFAULT_BRIGHTNESS); + eq(UserHandle.USER_CURRENT))).thenReturn(PowerManager.BRIGHTNESS_ON); + when(mDisplayManager.getBrightness(Display.DEFAULT_DISPLAY)) + .thenReturn(PowerManager.BRIGHTNESS_MAX); doAnswer(invocation -> { ((Runnable) invocation.getArgument(0)).run(); return null; @@ -117,9 +138,14 @@ public class DozeScreenBrightnessTest extends SysuiTestCase { mSensorManager = new AsyncSensorManager(fakeSensorManager, mFakeThreadFactory, null); mAlwaysOnDisplayPolicy = new AlwaysOnDisplayPolicy(mContext); - mAlwaysOnDisplayPolicy.defaultDozeBrightness = DEFAULT_BRIGHTNESS; - mAlwaysOnDisplayPolicy.screenBrightnessArray = SENSOR_TO_BRIGHTNESS; - mAlwaysOnDisplayPolicy.dimBrightness = DIM_BRIGHTNESS; + mAlwaysOnDisplayPolicy.defaultDozeBrightness = DEFAULT_BRIGHTNESS_INT; + when(mDisplayManager.getDefaultDozeBrightness(Display.DEFAULT_DISPLAY)) + .thenReturn(DEFAULT_BRIGHTNESS_FLOAT); + mAlwaysOnDisplayPolicy.screenBrightnessArray = SENSOR_TO_BRIGHTNESS_INT; + when(mDisplayManager.getDozeBrightnessSensorValueToBrightness(Display.DEFAULT_DISPLAY)) + .thenReturn(SENSOR_TO_BRIGHTNESS_FLOAT); + mAlwaysOnDisplayPolicy.dimBrightness = DIM_BRIGHTNESS_INT; + mAlwaysOnDisplayPolicy.dimBrightnessFloat = DIM_BRIGHTNESS_FLOAT; mAlwaysOnDisplayPolicy.dimmingScrimArray = SENSOR_TO_OPACITY; mSensor = fakeSensorManager.getFakeLightSensor(); mSensorInner = fakeSensorManager.getFakeLightSensor2(); @@ -135,19 +161,51 @@ public class DozeScreenBrightnessTest extends SysuiTestCase { mDozeParameters, mDevicePostureController, mDozeLog, - mSystemSettings); + mSystemSettings, + mDisplayManager); + } + + @Test + @RequiresFlagsDisabled(Flags.FLAG_DOZE_BRIGHTNESS_FLOAT) + public void testInitialize_setsScreenBrightnessToValidValue_Int() { + mScreen.transitionTo(UNINITIALIZED, INITIALIZED); + + assertEquals(DEFAULT_BRIGHTNESS_INT, mServiceFake.screenBrightnessInt); + assertTrue(mServiceFake.screenBrightnessInt >= PowerManager.BRIGHTNESS_OFF + 1); + assertTrue(mServiceFake.screenBrightnessInt <= PowerManager.BRIGHTNESS_ON); + assertTrue(Float.isNaN(mServiceFake.screenBrightnessFloat)); + } + + @Test + @RequiresFlagsEnabled(Flags.FLAG_DOZE_BRIGHTNESS_FLOAT) + public void testInitialize_setsScreenBrightnessToValidValue_Float() { + mScreen.transitionTo(UNINITIALIZED, INITIALIZED); + + assertEquals(DEFAULT_BRIGHTNESS_FLOAT, mServiceFake.screenBrightnessFloat, DELTA); + assertTrue(mServiceFake.screenBrightnessFloat >= PowerManager.BRIGHTNESS_MIN); + assertTrue(mServiceFake.screenBrightnessFloat <= PowerManager.BRIGHTNESS_MAX); + assertEquals(PowerManager.BRIGHTNESS_DEFAULT, mServiceFake.screenBrightnessInt); } @Test - public void testInitialize_setsScreenBrightnessToValidValue() throws Exception { + @RequiresFlagsDisabled(Flags.FLAG_DOZE_BRIGHTNESS_FLOAT) + public void testAod_usesDebugValue_Int() { mScreen.transitionTo(UNINITIALIZED, INITIALIZED); + mScreen.transitionTo(INITIALIZED, DOZE_AOD); + waitForSensorManager(); - assertEquals(DEFAULT_BRIGHTNESS, mServiceFake.screenBrightness); - assertTrue(mServiceFake.screenBrightness <= PowerManager.BRIGHTNESS_ON); + Intent intent = new Intent(DozeScreenBrightness.ACTION_AOD_BRIGHTNESS); + intent.putExtra(DozeScreenBrightness.BRIGHTNESS_BUCKET, 1); + mScreen.onReceive(mContext, intent); + mSensor.sendSensorEvent(3); + + assertEquals(SENSOR_TO_BRIGHTNESS_INT[1], mServiceFake.screenBrightnessInt); + assertTrue(Float.isNaN(mServiceFake.screenBrightnessFloat)); } @Test - public void testAod_usesDebugValue() throws Exception { + @RequiresFlagsEnabled(Flags.FLAG_DOZE_BRIGHTNESS_FLOAT) + public void testAod_usesDebugValue_Float() { mScreen.transitionTo(UNINITIALIZED, INITIALIZED); mScreen.transitionTo(INITIALIZED, DOZE_AOD); waitForSensorManager(); @@ -157,11 +215,13 @@ public class DozeScreenBrightnessTest extends SysuiTestCase { mScreen.onReceive(mContext, intent); mSensor.sendSensorEvent(3); - assertEquals(1, mServiceFake.screenBrightness); + assertEquals(SENSOR_TO_BRIGHTNESS_FLOAT[1], mServiceFake.screenBrightnessFloat, DELTA); + assertEquals(PowerManager.BRIGHTNESS_DEFAULT, mServiceFake.screenBrightnessInt); } @Test - public void testAod_usesLightSensorRespectingUserSetting() { + @RequiresFlagsDisabled(Flags.FLAG_DOZE_BRIGHTNESS_FLOAT) + public void testAod_usesLightSensorRespectingUserSetting_Int() { int maxBrightness = 3; when(mSystemSettings.getIntForUser(eq(Settings.System.SCREEN_BRIGHTNESS), anyInt(), eq(UserHandle.USER_CURRENT))).thenReturn(maxBrightness); @@ -170,11 +230,27 @@ public class DozeScreenBrightnessTest extends SysuiTestCase { .thenReturn(Settings.System.SCREEN_BRIGHTNESS_MODE_MANUAL); mScreen.transitionTo(UNINITIALIZED, INITIALIZED); - assertEquals(maxBrightness, mServiceFake.screenBrightness); + assertEquals(maxBrightness, mServiceFake.screenBrightnessInt); + assertTrue(Float.isNaN(mServiceFake.screenBrightnessFloat)); + } + + @Test + @RequiresFlagsEnabled(Flags.FLAG_DOZE_BRIGHTNESS_FLOAT) + public void testAod_usesLightSensorRespectingUserSetting_Float() { + float maxBrightness = DEFAULT_BRIGHTNESS_FLOAT / 2; + when(mDisplayManager.getBrightness(Display.DEFAULT_DISPLAY)).thenReturn(maxBrightness); + when(mSystemSettings.getIntForUser(eq(Settings.System.SCREEN_BRIGHTNESS_MODE), anyInt(), + eq(UserHandle.USER_CURRENT))) + .thenReturn(Settings.System.SCREEN_BRIGHTNESS_MODE_MANUAL); + + mScreen.transitionTo(UNINITIALIZED, INITIALIZED); + assertEquals(maxBrightness, mServiceFake.screenBrightnessFloat, DELTA); + assertEquals(PowerManager.BRIGHTNESS_DEFAULT, mServiceFake.screenBrightnessInt); } @Test - public void testAod_usesLightSensorNotClampingToAutoBrightnessValue() { + @RequiresFlagsDisabled(Flags.FLAG_DOZE_BRIGHTNESS_FLOAT) + public void testAod_usesLightSensorNotClampingToAutoBrightnessValue_Int() { int maxBrightness = 3; when(mSystemSettings.getIntForUser(eq(Settings.System.SCREEN_BRIGHTNESS), anyInt(), eq(UserHandle.USER_CURRENT))).thenReturn(maxBrightness); @@ -183,11 +259,27 @@ public class DozeScreenBrightnessTest extends SysuiTestCase { .thenReturn(Settings.System.SCREEN_BRIGHTNESS_MODE_AUTOMATIC); mScreen.transitionTo(UNINITIALIZED, INITIALIZED); - assertEquals(DEFAULT_BRIGHTNESS, mServiceFake.screenBrightness); + assertEquals(DEFAULT_BRIGHTNESS_INT, mServiceFake.screenBrightnessInt); + assertTrue(Float.isNaN(mServiceFake.screenBrightnessFloat)); + } + + @Test + @RequiresFlagsEnabled(Flags.FLAG_DOZE_BRIGHTNESS_FLOAT) + public void testAod_usesLightSensorNotClampingToAutoBrightnessValue_Float() { + float maxBrightness = DEFAULT_BRIGHTNESS_FLOAT / 2; + when(mDisplayManager.getBrightness(Display.DEFAULT_DISPLAY)).thenReturn(maxBrightness); + when(mSystemSettings.getIntForUser(eq(Settings.System.SCREEN_BRIGHTNESS_MODE), anyInt(), + eq(UserHandle.USER_CURRENT))) + .thenReturn(Settings.System.SCREEN_BRIGHTNESS_MODE_AUTOMATIC); + + mScreen.transitionTo(UNINITIALIZED, INITIALIZED); + assertEquals(DEFAULT_BRIGHTNESS_FLOAT, mServiceFake.screenBrightnessFloat, DELTA); + assertEquals(PowerManager.BRIGHTNESS_DEFAULT, mServiceFake.screenBrightnessInt); } @Test - public void doze_doesNotUseLightSensor() { + @RequiresFlagsDisabled(Flags.FLAG_DOZE_BRIGHTNESS_FLOAT) + public void doze_doesNotUseLightSensor_Int() { // GIVEN the device is DOZE and the display state changes to ON mScreen.transitionTo(UNINITIALIZED, INITIALIZED); mScreen.transitionTo(INITIALIZED, DOZE); @@ -197,12 +289,48 @@ public class DozeScreenBrightnessTest extends SysuiTestCase { mSensor.sendSensorEvent(3); // THEN brightness is NOT changed, it's set to the default brightness - assertNotSame(3, mServiceFake.screenBrightness); - assertEquals(DEFAULT_BRIGHTNESS, mServiceFake.screenBrightness); + assertNotSame(SENSOR_TO_BRIGHTNESS_INT[3], mServiceFake.screenBrightnessInt); + assertEquals(DEFAULT_BRIGHTNESS_INT, mServiceFake.screenBrightnessInt); + assertTrue(Float.isNaN(mServiceFake.screenBrightnessFloat)); } @Test - public void dozeSuspendTriggers_doesNotUseLightSensor() { + @RequiresFlagsEnabled(Flags.FLAG_DOZE_BRIGHTNESS_FLOAT) + public void doze_doesNotUseLightSensor_Float() { + // GIVEN the device is DOZE and the display state changes to ON + mScreen.transitionTo(UNINITIALIZED, INITIALIZED); + mScreen.transitionTo(INITIALIZED, DOZE); + waitForSensorManager(); + + // WHEN new sensor event sent + mSensor.sendSensorEvent(3); + + // THEN brightness is NOT changed, it's set to the default brightness + assertNotSame(SENSOR_TO_BRIGHTNESS_FLOAT[3], mServiceFake.screenBrightnessInt); + assertEquals(DEFAULT_BRIGHTNESS_FLOAT, mServiceFake.screenBrightnessFloat, DELTA); + assertEquals(PowerManager.BRIGHTNESS_DEFAULT, mServiceFake.screenBrightnessInt); + } + + @Test + @RequiresFlagsDisabled(Flags.FLAG_DOZE_BRIGHTNESS_FLOAT) + public void dozeSuspendTriggers_doesNotUseLightSensor_Int() { + // GIVEN the device is DOZE and the display state changes to ON + mScreen.transitionTo(UNINITIALIZED, INITIALIZED); + mScreen.transitionTo(INITIALIZED, DOZE_SUSPEND_TRIGGERS); + waitForSensorManager(); + + // WHEN new sensor event sent + mSensor.sendSensorEvent(3); + + // THEN brightness is NOT changed, it's set to the default brightness + assertNotSame(SENSOR_TO_BRIGHTNESS_INT[3], mServiceFake.screenBrightnessInt); + assertEquals(DEFAULT_BRIGHTNESS_INT, mServiceFake.screenBrightnessInt); + assertTrue(Float.isNaN(mServiceFake.screenBrightnessFloat)); + } + + @Test + @RequiresFlagsEnabled(Flags.FLAG_DOZE_BRIGHTNESS_FLOAT) + public void dozeSuspendTriggers_doesNotUseLightSensor_Float() { // GIVEN the device is DOZE and the display state changes to ON mScreen.transitionTo(UNINITIALIZED, INITIALIZED); mScreen.transitionTo(INITIALIZED, DOZE_SUSPEND_TRIGGERS); @@ -212,12 +340,14 @@ public class DozeScreenBrightnessTest extends SysuiTestCase { mSensor.sendSensorEvent(3); // THEN brightness is NOT changed, it's set to the default brightness - assertNotSame(3, mServiceFake.screenBrightness); - assertEquals(DEFAULT_BRIGHTNESS, mServiceFake.screenBrightness); + assertNotSame(SENSOR_TO_BRIGHTNESS_FLOAT[3], mServiceFake.screenBrightnessFloat); + assertEquals(DEFAULT_BRIGHTNESS_FLOAT, mServiceFake.screenBrightnessFloat, DELTA); + assertEquals(PowerManager.BRIGHTNESS_DEFAULT, mServiceFake.screenBrightnessInt); } @Test - public void aod_usesLightSensor() { + @RequiresFlagsDisabled(Flags.FLAG_DOZE_BRIGHTNESS_FLOAT) + public void aod_usesLightSensor_Int() { // GIVEN the device is DOZE_AOD and the display state changes to ON mScreen.transitionTo(UNINITIALIZED, INITIALIZED); mScreen.transitionTo(INITIALIZED, DOZE_AOD); @@ -227,11 +357,29 @@ public class DozeScreenBrightnessTest extends SysuiTestCase { mSensor.sendSensorEvent(3); // THEN brightness is updated - assertEquals(3, mServiceFake.screenBrightness); + assertEquals(SENSOR_TO_BRIGHTNESS_INT[3], mServiceFake.screenBrightnessInt); + assertTrue(Float.isNaN(mServiceFake.screenBrightnessFloat)); } @Test - public void docked_usesLightSensor() { + @RequiresFlagsEnabled(Flags.FLAG_DOZE_BRIGHTNESS_FLOAT) + public void aod_usesLightSensor_Float() { + // GIVEN the device is DOZE_AOD and the display state changes to ON + mScreen.transitionTo(UNINITIALIZED, INITIALIZED); + mScreen.transitionTo(INITIALIZED, DOZE_AOD); + waitForSensorManager(); + + // WHEN new sensor event sent + mSensor.sendSensorEvent(3); + + // THEN brightness is updated + assertEquals(SENSOR_TO_BRIGHTNESS_FLOAT[3], mServiceFake.screenBrightnessFloat, DELTA); + assertEquals(PowerManager.BRIGHTNESS_DEFAULT, mServiceFake.screenBrightnessInt); + } + + @Test + @RequiresFlagsDisabled(Flags.FLAG_DOZE_BRIGHTNESS_FLOAT) + public void docked_usesLightSensor_Int() { // GIVEN the device is docked and the display state changes to ON mScreen.transitionTo(UNINITIALIZED, INITIALIZED); mScreen.transitionTo(INITIALIZED, DOZE_AOD); @@ -242,11 +390,29 @@ public class DozeScreenBrightnessTest extends SysuiTestCase { mSensor.sendSensorEvent(3); // THEN brightness is updated - assertEquals(3, mServiceFake.screenBrightness); + assertEquals(SENSOR_TO_BRIGHTNESS_INT[3], mServiceFake.screenBrightnessInt); + assertTrue(Float.isNaN(mServiceFake.screenBrightnessFloat)); } @Test - public void testPulsing_withoutLightSensor_setsAoDDimmingScrimTransparent() throws Exception { + @RequiresFlagsEnabled(Flags.FLAG_DOZE_BRIGHTNESS_FLOAT) + public void docked_usesLightSensor_Float() { + // GIVEN the device is docked and the display state changes to ON + mScreen.transitionTo(UNINITIALIZED, INITIALIZED); + mScreen.transitionTo(INITIALIZED, DOZE_AOD); + mScreen.transitionTo(DOZE_AOD, DOZE_AOD_DOCKED); + waitForSensorManager(); + + // WHEN new sensor event sent + mSensor.sendSensorEvent(3); + + // THEN brightness is updated + assertEquals(SENSOR_TO_BRIGHTNESS_FLOAT[3], mServiceFake.screenBrightnessFloat, DELTA); + assertEquals(PowerManager.BRIGHTNESS_DEFAULT, mServiceFake.screenBrightnessInt); + } + + @Test + public void testPulsing_withoutLightSensor_setsAoDDimmingScrimTransparent() { mScreen = new DozeScreenBrightness( mContext, mServiceFake, @@ -258,7 +424,8 @@ public class DozeScreenBrightnessTest extends SysuiTestCase { mDozeParameters, mDevicePostureController, mDozeLog, - mSystemSettings); + mSystemSettings, + mDisplayManager); mScreen.transitionTo(UNINITIALIZED, INITIALIZED); mScreen.transitionTo(INITIALIZED, DOZE); reset(mDozeHost); @@ -269,7 +436,8 @@ public class DozeScreenBrightnessTest extends SysuiTestCase { } @Test - public void testScreenOffAfterPulsing_pausesLightSensor() throws Exception { + @RequiresFlagsDisabled(Flags.FLAG_DOZE_BRIGHTNESS_FLOAT) + public void testScreenOffAfterPulsing_pausesLightSensor_Int() { mScreen.transitionTo(UNINITIALIZED, INITIALIZED); mScreen.transitionTo(INITIALIZED, DOZE); mScreen.transitionTo(DOZE, DOZE_REQUEST_PULSE); @@ -280,11 +448,29 @@ public class DozeScreenBrightnessTest extends SysuiTestCase { mSensor.sendSensorEvent(1); - assertEquals(DEFAULT_BRIGHTNESS, mServiceFake.screenBrightness); + assertEquals(DEFAULT_BRIGHTNESS_INT, mServiceFake.screenBrightnessInt); + assertTrue(Float.isNaN(mServiceFake.screenBrightnessFloat)); } @Test - public void testNullSensor() throws Exception { + @RequiresFlagsEnabled(Flags.FLAG_DOZE_BRIGHTNESS_FLOAT) + public void testScreenOffAfterPulsing_pausesLightSensor_Float() { + mScreen.transitionTo(UNINITIALIZED, INITIALIZED); + mScreen.transitionTo(INITIALIZED, DOZE); + mScreen.transitionTo(DOZE, DOZE_REQUEST_PULSE); + mScreen.transitionTo(DOZE_REQUEST_PULSE, DOZE_PULSING); + mScreen.transitionTo(DOZE_PULSING, DOZE_PULSE_DONE); + mScreen.transitionTo(DOZE_PULSE_DONE, DOZE); + waitForSensorManager(); + + mSensor.sendSensorEvent(1); + + assertEquals(DEFAULT_BRIGHTNESS_FLOAT, mServiceFake.screenBrightnessFloat, DELTA); + assertEquals(PowerManager.BRIGHTNESS_DEFAULT, mServiceFake.screenBrightnessInt); + } + + @Test + public void testNullSensor() { mScreen = new DozeScreenBrightness( mContext, mServiceFake, @@ -296,7 +482,8 @@ public class DozeScreenBrightnessTest extends SysuiTestCase { mDozeParameters, mDevicePostureController, mDozeLog, - mSystemSettings); + mSystemSettings, + mDisplayManager); mScreen.transitionTo(UNINITIALIZED, INITIALIZED); mScreen.transitionTo(INITIALIZED, DOZE_AOD); @@ -305,7 +492,50 @@ public class DozeScreenBrightnessTest extends SysuiTestCase { } @Test - public void testSensorsSupportPostures_closed() throws Exception { + @RequiresFlagsDisabled(Flags.FLAG_DOZE_BRIGHTNESS_FLOAT) + public void testSensorsSupportPostures_closed_Int() { + // GIVEN the device is CLOSED + when(mDevicePostureController.getDevicePosture()).thenReturn( + DevicePostureController.DEVICE_POSTURE_CLOSED); + + // GIVEN closed and opened postures use different light sensors + mScreen = new DozeScreenBrightness( + mContext, + mServiceFake, + mSensorManager, + new Optional[]{ + Optional.empty() /* unknown */, + Optional.of(mSensor.getSensor()) /* closed */, + Optional.of(mSensorInner.getSensor()) /* half-opened */, + Optional.of(mSensorInner.getSensor()) /* opened */, + Optional.empty() /* flipped */ + }, + mDozeHost, null /* handler */, + mAlwaysOnDisplayPolicy, + mWakefulnessLifecycle, + mDozeParameters, + mDevicePostureController, + mDozeLog, + mSystemSettings, + mDisplayManager); + + // GIVEN the device is in AOD + mScreen.transitionTo(UNINITIALIZED, INITIALIZED); + mScreen.transitionTo(INITIALIZED, DOZE_AOD); + waitForSensorManager(); + + // WHEN new different events are sent from the inner and outer sensors + mSensor.sendSensorEvent(3); // CLOSED sensor + mSensorInner.sendSensorEvent(4); // OPENED sensor + + // THEN brightness is updated according to the sensor for CLOSED + assertEquals(SENSOR_TO_BRIGHTNESS_INT[3], mServiceFake.screenBrightnessInt); + assertTrue(Float.isNaN(mServiceFake.screenBrightnessFloat)); + } + + @Test + @RequiresFlagsEnabled(Flags.FLAG_DOZE_BRIGHTNESS_FLOAT) + public void testSensorsSupportPostures_closed_Float() { // GIVEN the device is CLOSED when(mDevicePostureController.getDevicePosture()).thenReturn( DevicePostureController.DEVICE_POSTURE_CLOSED); @@ -328,7 +558,8 @@ public class DozeScreenBrightnessTest extends SysuiTestCase { mDozeParameters, mDevicePostureController, mDozeLog, - mSystemSettings); + mSystemSettings, + mDisplayManager); // GIVEN the device is in AOD mScreen.transitionTo(UNINITIALIZED, INITIALIZED); @@ -340,11 +571,14 @@ public class DozeScreenBrightnessTest extends SysuiTestCase { mSensorInner.sendSensorEvent(4); // OPENED sensor // THEN brightness is updated according to the sensor for CLOSED - assertEquals(3, mServiceFake.screenBrightness); + assertEquals(SENSOR_TO_BRIGHTNESS_FLOAT[3], mServiceFake.screenBrightnessFloat, + DELTA); + assertEquals(PowerManager.BRIGHTNESS_DEFAULT, mServiceFake.screenBrightnessInt); } @Test - public void testSensorsSupportPostures_open() throws Exception { + @RequiresFlagsDisabled(Flags.FLAG_DOZE_BRIGHTNESS_FLOAT) + public void testSensorsSupportPostures_open_Int() { // GIVEN the device is OPENED when(mDevicePostureController.getDevicePosture()).thenReturn( DevicePostureController.DEVICE_POSTURE_OPENED); @@ -367,7 +601,8 @@ public class DozeScreenBrightnessTest extends SysuiTestCase { mDozeParameters, mDevicePostureController, mDozeLog, - mSystemSettings); + mSystemSettings, + mDisplayManager); // GIVEN device is in AOD mScreen.transitionTo(UNINITIALIZED, INITIALIZED); @@ -379,11 +614,55 @@ public class DozeScreenBrightnessTest extends SysuiTestCase { mSensor.sendSensorEvent(3); // CLOSED sensor // THEN brightness is updated according to the sensor for OPENED - assertEquals(4, mServiceFake.screenBrightness); + assertEquals(SENSOR_TO_BRIGHTNESS_INT[4], mServiceFake.screenBrightnessInt); + assertTrue(Float.isNaN(mServiceFake.screenBrightnessFloat)); } @Test - public void testSensorsSupportPostures_swapPostures() throws Exception { + @RequiresFlagsEnabled(Flags.FLAG_DOZE_BRIGHTNESS_FLOAT) + public void testSensorsSupportPostures_open_Float() { + // GIVEN the device is OPENED + when(mDevicePostureController.getDevicePosture()).thenReturn( + DevicePostureController.DEVICE_POSTURE_OPENED); + + // GIVEN closed and opened postures use different light sensors + mScreen = new DozeScreenBrightness( + mContext, + mServiceFake, + mSensorManager, + new Optional[]{ + Optional.empty() /* unknown */, + Optional.of(mSensor.getSensor()) /* closed */, + Optional.of(mSensorInner.getSensor()) /* half-opened */, + Optional.of(mSensorInner.getSensor()) /* opened */, + Optional.empty() /* flipped */ + }, + mDozeHost, null /* handler */, + mAlwaysOnDisplayPolicy, + mWakefulnessLifecycle, + mDozeParameters, + mDevicePostureController, + mDozeLog, + mSystemSettings, + mDisplayManager); + + // GIVEN device is in AOD + mScreen.transitionTo(UNINITIALIZED, INITIALIZED); + mScreen.transitionTo(INITIALIZED, DOZE_AOD); + waitForSensorManager(); + + // WHEN new different events are sent from the inner and outer sensors + mSensorInner.sendSensorEvent(4); // OPENED sensor + mSensor.sendSensorEvent(3); // CLOSED sensor + + // THEN brightness is updated according to the sensor for OPENED + assertEquals(SENSOR_TO_BRIGHTNESS_FLOAT[4], mServiceFake.screenBrightnessFloat, DELTA); + assertEquals(PowerManager.BRIGHTNESS_DEFAULT, mServiceFake.screenBrightnessInt); + } + + @Test + @RequiresFlagsDisabled(Flags.FLAG_DOZE_BRIGHTNESS_FLOAT) + public void testSensorsSupportPostures_swapPostures_Int() { ArgumentCaptor<DevicePostureController.Callback> postureCallbackCaptor = ArgumentCaptor.forClass(DevicePostureController.Callback.class); reset(mDevicePostureController); @@ -410,7 +689,8 @@ public class DozeScreenBrightnessTest extends SysuiTestCase { mDozeParameters, mDevicePostureController, mDozeLog, - mSystemSettings); + mSystemSettings, + mDisplayManager); verify(mDevicePostureController).addCallback(postureCallbackCaptor.capture()); // GIVEN device is in AOD @@ -428,11 +708,79 @@ public class DozeScreenBrightnessTest extends SysuiTestCase { mSensorInner.sendSensorEvent(4); // OPENED sensor // THEN brightness is updated according to the sensor for CLOSED - assertEquals(3, mServiceFake.screenBrightness); + assertEquals(SENSOR_TO_BRIGHTNESS_INT[3], mServiceFake.screenBrightnessInt); + assertTrue(Float.isNaN(mServiceFake.screenBrightnessFloat)); } @Test - public void testNoBrightnessDeliveredAfterFinish() throws Exception { + @RequiresFlagsEnabled(Flags.FLAG_DOZE_BRIGHTNESS_FLOAT) + public void testSensorsSupportPostures_swapPostures_Float() { + ArgumentCaptor<DevicePostureController.Callback> postureCallbackCaptor = + ArgumentCaptor.forClass(DevicePostureController.Callback.class); + reset(mDevicePostureController); + + // GIVEN the device starts up AOD OPENED + when(mDevicePostureController.getDevicePosture()).thenReturn( + DevicePostureController.DEVICE_POSTURE_OPENED); + + // GIVEN closed and opened postures use different light sensors + mScreen = new DozeScreenBrightness( + mContext, + mServiceFake, + mSensorManager, + new Optional[]{ + Optional.empty() /* unknown */, + Optional.of(mSensor.getSensor()) /* closed */, + Optional.of(mSensorInner.getSensor()) /* half-opened */, + Optional.of(mSensorInner.getSensor()) /* opened */, + Optional.empty() /* flipped */ + }, + mDozeHost, null /* handler */, + mAlwaysOnDisplayPolicy, + mWakefulnessLifecycle, + mDozeParameters, + mDevicePostureController, + mDozeLog, + mSystemSettings, + mDisplayManager); + verify(mDevicePostureController).addCallback(postureCallbackCaptor.capture()); + + // GIVEN device is in AOD + mScreen.transitionTo(UNINITIALIZED, INITIALIZED); + mScreen.transitionTo(INITIALIZED, DOZE_AOD); + waitForSensorManager(); + + // WHEN the posture changes to CLOSED + postureCallbackCaptor.getValue().onPostureChanged( + DevicePostureController.DEVICE_POSTURE_CLOSED); + waitForSensorManager(); + + // WHEN new different events are sent from the inner and outer sensors + mSensor.sendSensorEvent(3); // CLOSED sensor + mSensorInner.sendSensorEvent(4); // OPENED sensor + + // THEN brightness is updated according to the sensor for CLOSED + assertEquals(SENSOR_TO_BRIGHTNESS_FLOAT[3], mServiceFake.screenBrightnessFloat, DELTA); + assertEquals(PowerManager.BRIGHTNESS_DEFAULT, mServiceFake.screenBrightnessInt); + } + + @Test + @RequiresFlagsDisabled(Flags.FLAG_DOZE_BRIGHTNESS_FLOAT) + public void testNoBrightnessDeliveredAfterFinish_Int() { + mScreen.transitionTo(UNINITIALIZED, INITIALIZED); + mScreen.transitionTo(INITIALIZED, DOZE_AOD); + mScreen.transitionTo(DOZE_AOD, FINISH); + waitForSensorManager(); + + mSensor.sendSensorEvent(1); + + assertNotEquals(SENSOR_TO_BRIGHTNESS_INT[1], mServiceFake.screenBrightnessInt); + assertTrue(Float.isNaN(mServiceFake.screenBrightnessFloat)); + } + + @Test + @RequiresFlagsEnabled(Flags.FLAG_DOZE_BRIGHTNESS_FLOAT) + public void testNoBrightnessDeliveredAfterFinish_Float() { mScreen.transitionTo(UNINITIALIZED, INITIALIZED); mScreen.transitionTo(INITIALIZED, DOZE_AOD); mScreen.transitionTo(DOZE_AOD, FINISH); @@ -440,11 +788,28 @@ public class DozeScreenBrightnessTest extends SysuiTestCase { mSensor.sendSensorEvent(1); - assertNotEquals(1, mServiceFake.screenBrightness); + assertNotEquals(SENSOR_TO_BRIGHTNESS_FLOAT[1], mServiceFake.screenBrightnessFloat); + assertEquals(PowerManager.BRIGHTNESS_DEFAULT, mServiceFake.screenBrightnessInt); + } + + @Test + @RequiresFlagsDisabled(Flags.FLAG_DOZE_BRIGHTNESS_FLOAT) + public void testNonPositiveBrightness_keepsPreviousBrightnessAndScrim_Int() { + mScreen.transitionTo(UNINITIALIZED, INITIALIZED); + mScreen.transitionTo(INITIALIZED, DOZE_AOD); + waitForSensorManager(); + + mSensor.sendSensorEvent(1); + mSensor.sendSensorEvent(0); + + assertEquals(SENSOR_TO_BRIGHTNESS_INT[1], mServiceFake.screenBrightnessInt); + assertTrue(Float.isNaN(mServiceFake.screenBrightnessFloat)); + verify(mDozeHost).setAodDimmingScrim(eq(10f / 255f)); } @Test - public void testNonPositiveBrightness_keepsPreviousBrightnessAndScrim() { + @RequiresFlagsEnabled(Flags.FLAG_DOZE_BRIGHTNESS_FLOAT) + public void testNonPositiveBrightness_keepsPreviousBrightnessAndScrim_Float() { mScreen.transitionTo(UNINITIALIZED, INITIALIZED); mScreen.transitionTo(INITIALIZED, DOZE_AOD); waitForSensorManager(); @@ -452,7 +817,8 @@ public class DozeScreenBrightnessTest extends SysuiTestCase { mSensor.sendSensorEvent(1); mSensor.sendSensorEvent(0); - assertEquals(1, mServiceFake.screenBrightness); + assertEquals(SENSOR_TO_BRIGHTNESS_FLOAT[1], mServiceFake.screenBrightnessFloat, DELTA); + assertEquals(PowerManager.BRIGHTNESS_DEFAULT, mServiceFake.screenBrightnessInt); verify(mDozeHost).setAodDimmingScrim(eq(10f / 255f)); } @@ -473,7 +839,8 @@ public class DozeScreenBrightnessTest extends SysuiTestCase { } @Test - public void transitionToDoze_shouldClampBrightness_afterTimeout_clampsToDim() { + @RequiresFlagsDisabled(Flags.FLAG_DOZE_BRIGHTNESS_FLOAT) + public void transitionToDoze_shouldClampBrightness_afterTimeout_clampsToDim_Int() { when(mWakefulnessLifecycle.getLastSleepReason()).thenReturn( PowerManager.GO_TO_SLEEP_REASON_TIMEOUT); when(mDozeParameters.shouldClampToDimBrightness()).thenReturn(true); @@ -482,15 +849,57 @@ public class DozeScreenBrightnessTest extends SysuiTestCase { // If we're dozing after a timeout, and playing the unlocked screen animation, we should // stay at or below dim brightness, because the screen dims just before timeout. - assertTrue(mServiceFake.screenBrightness <= DIM_BRIGHTNESS); + assertTrue(mServiceFake.screenBrightnessInt <= DIM_BRIGHTNESS_INT); + assertTrue(Float.isNaN(mServiceFake.screenBrightnessFloat)); // Once we transition to Doze, use the doze brightness mScreen.transitionTo(INITIALIZED, DOZE); - assertEquals(mServiceFake.screenBrightness, DEFAULT_BRIGHTNESS); + assertEquals(mServiceFake.screenBrightnessInt, DEFAULT_BRIGHTNESS_INT); + assertTrue(Float.isNaN(mServiceFake.screenBrightnessFloat)); + } + + @Test + @RequiresFlagsEnabled(Flags.FLAG_DOZE_BRIGHTNESS_FLOAT) + public void transitionToDoze_shouldClampBrightness_afterTimeout_clampsToDim_Float() { + when(mWakefulnessLifecycle.getLastSleepReason()).thenReturn( + PowerManager.GO_TO_SLEEP_REASON_TIMEOUT); + when(mDozeParameters.shouldClampToDimBrightness()).thenReturn(true); + + mScreen.transitionTo(UNINITIALIZED, INITIALIZED); + + // If we're dozing after a timeout, and playing the unlocked screen animation, we should + // stay at or below dim brightness, because the screen dims just before timeout. + assertTrue(mServiceFake.screenBrightnessFloat <= DIM_BRIGHTNESS_FLOAT); + assertEquals(PowerManager.BRIGHTNESS_DEFAULT, mServiceFake.screenBrightnessInt); + + // Once we transition to Doze, use the doze brightness + mScreen.transitionTo(INITIALIZED, DOZE); + assertEquals(mServiceFake.screenBrightnessFloat, DEFAULT_BRIGHTNESS_FLOAT, DELTA); + assertEquals(PowerManager.BRIGHTNESS_DEFAULT, mServiceFake.screenBrightnessInt); + } + + @Test + @RequiresFlagsDisabled(Flags.FLAG_DOZE_BRIGHTNESS_FLOAT) + public void transitionToDoze_shouldClampBrightness_notAfterTimeout_doesNotClampToDim_Int() { + when(mWakefulnessLifecycle.getLastSleepReason()).thenReturn( + PowerManager.GO_TO_SLEEP_REASON_POWER_BUTTON); + when(mDozeParameters.shouldClampToDimBrightness()).thenReturn(true); + + mScreen.transitionTo(UNINITIALIZED, INITIALIZED); + + // If we're playing the unlocked screen off animation after a power button press, we should + // leave the brightness alone. + assertEquals(mServiceFake.screenBrightnessInt, DEFAULT_BRIGHTNESS_INT); + assertTrue(Float.isNaN(mServiceFake.screenBrightnessFloat)); + + mScreen.transitionTo(INITIALIZED, DOZE); + assertEquals(mServiceFake.screenBrightnessInt, DEFAULT_BRIGHTNESS_INT); + assertTrue(Float.isNaN(mServiceFake.screenBrightnessFloat)); } @Test - public void transitionToDoze_shouldClampBrightness_notAfterTimeout_doesNotClampToDim() { + @RequiresFlagsEnabled(Flags.FLAG_DOZE_BRIGHTNESS_FLOAT) + public void transitionToDoze_shouldClampBrightness_notAfterTimeout_doesNotClampToDim_Float() { when(mWakefulnessLifecycle.getLastSleepReason()).thenReturn( PowerManager.GO_TO_SLEEP_REASON_POWER_BUTTON); when(mDozeParameters.shouldClampToDimBrightness()).thenReturn(true); @@ -499,14 +908,32 @@ public class DozeScreenBrightnessTest extends SysuiTestCase { // If we're playing the unlocked screen off animation after a power button press, we should // leave the brightness alone. - assertEquals(mServiceFake.screenBrightness, DEFAULT_BRIGHTNESS); + assertEquals(mServiceFake.screenBrightnessFloat, DEFAULT_BRIGHTNESS_FLOAT, DELTA); + assertEquals(PowerManager.BRIGHTNESS_DEFAULT, mServiceFake.screenBrightnessInt); + + mScreen.transitionTo(INITIALIZED, DOZE); + assertEquals(mServiceFake.screenBrightnessFloat, DEFAULT_BRIGHTNESS_FLOAT, DELTA); + assertEquals(PowerManager.BRIGHTNESS_DEFAULT, mServiceFake.screenBrightnessInt); + } + + @Test + @RequiresFlagsDisabled(Flags.FLAG_DOZE_BRIGHTNESS_FLOAT) + public void transitionToDoze_noClamp_afterTimeout_noScreenOff_doesNotClampToDim_Int() { + when(mWakefulnessLifecycle.getLastSleepReason()).thenReturn( + PowerManager.GO_TO_SLEEP_REASON_TIMEOUT); + when(mDozeParameters.shouldClampToDimBrightness()).thenReturn(false); + mScreen.transitionTo(UNINITIALIZED, INITIALIZED); mScreen.transitionTo(INITIALIZED, DOZE); - assertEquals(mServiceFake.screenBrightness, DEFAULT_BRIGHTNESS); + + // If we aren't controlling the screen off animation, we should leave the brightness alone. + assertEquals(mServiceFake.screenBrightnessInt, DEFAULT_BRIGHTNESS_INT); + assertTrue(Float.isNaN(mServiceFake.screenBrightnessFloat)); } @Test - public void transitionToDoze_noClampBrightness_afterTimeout_noScreenOff_doesNotClampToDim() { + @RequiresFlagsEnabled(Flags.FLAG_DOZE_BRIGHTNESS_FLOAT) + public void transitionToDoze_noClamp_afterTimeout_noScreenOff_doesNotClampToDim_Float() { when(mWakefulnessLifecycle.getLastSleepReason()).thenReturn( PowerManager.GO_TO_SLEEP_REASON_TIMEOUT); when(mDozeParameters.shouldClampToDimBrightness()).thenReturn(false); @@ -515,11 +942,13 @@ public class DozeScreenBrightnessTest extends SysuiTestCase { mScreen.transitionTo(INITIALIZED, DOZE); // If we aren't controlling the screen off animation, we should leave the brightness alone. - assertEquals(mServiceFake.screenBrightness, DEFAULT_BRIGHTNESS); + assertEquals(mServiceFake.screenBrightnessFloat, DEFAULT_BRIGHTNESS_FLOAT, DELTA); + assertEquals(PowerManager.BRIGHTNESS_DEFAULT, mServiceFake.screenBrightnessInt); } @Test - public void transitionToDoze_noClampBrightness_afterTimeout_clampsToDim() { + @RequiresFlagsDisabled(Flags.FLAG_DOZE_BRIGHTNESS_FLOAT) + public void transitionToDoze_noClampBrightness_afterTimeout_clampsToDim_Int() { when(mWakefulnessLifecycle.getLastSleepReason()).thenReturn( PowerManager.GO_TO_SLEEP_REASON_TIMEOUT); when(mWakefulnessLifecycle.getWakefulness()).thenReturn( @@ -528,11 +957,28 @@ public class DozeScreenBrightnessTest extends SysuiTestCase { mScreen.transitionTo(UNINITIALIZED, INITIALIZED); - assertTrue(mServiceFake.screenBrightness <= DIM_BRIGHTNESS); + assertTrue(mServiceFake.screenBrightnessInt <= DIM_BRIGHTNESS_INT); + assertTrue(Float.isNaN(mServiceFake.screenBrightnessFloat)); } @Test - public void transitionToDoze_noClampBrigthness_notAfterTimeout_doesNotClampToDim() { + @RequiresFlagsEnabled(Flags.FLAG_DOZE_BRIGHTNESS_FLOAT) + public void transitionToDoze_noClampBrightness_afterTimeout_clampsToDim_Float() { + when(mWakefulnessLifecycle.getLastSleepReason()).thenReturn( + PowerManager.GO_TO_SLEEP_REASON_TIMEOUT); + when(mWakefulnessLifecycle.getWakefulness()).thenReturn( + WakefulnessLifecycle.WAKEFULNESS_GOING_TO_SLEEP); + when(mDozeParameters.shouldClampToDimBrightness()).thenReturn(false); + + mScreen.transitionTo(UNINITIALIZED, INITIALIZED); + + assertTrue(mServiceFake.screenBrightnessFloat <= DIM_BRIGHTNESS_FLOAT); + assertEquals(PowerManager.BRIGHTNESS_DEFAULT, mServiceFake.screenBrightnessInt); + } + + @Test + @RequiresFlagsDisabled(Flags.FLAG_DOZE_BRIGHTNESS_FLOAT) + public void transitionToDoze_noClampBrigthness_notAfterTimeout_doesNotClampToDim_Int() { when(mWakefulnessLifecycle.getLastSleepReason()).thenReturn( PowerManager.GO_TO_SLEEP_REASON_POWER_BUTTON); when(mWakefulnessLifecycle.getWakefulness()).thenReturn( @@ -542,11 +988,47 @@ public class DozeScreenBrightnessTest extends SysuiTestCase { mScreen.transitionTo(UNINITIALIZED, INITIALIZED); mScreen.transitionTo(INITIALIZED, DOZE); - assertEquals(mServiceFake.screenBrightness, DEFAULT_BRIGHTNESS); + assertEquals(mServiceFake.screenBrightnessInt, DEFAULT_BRIGHTNESS_INT); + assertTrue(Float.isNaN(mServiceFake.screenBrightnessFloat)); + } + + @Test + @RequiresFlagsEnabled(Flags.FLAG_DOZE_BRIGHTNESS_FLOAT) + public void transitionToDoze_noClampBrigthness_notAfterTimeout_doesNotClampToDim_Float() { + when(mWakefulnessLifecycle.getLastSleepReason()).thenReturn( + PowerManager.GO_TO_SLEEP_REASON_POWER_BUTTON); + when(mWakefulnessLifecycle.getWakefulness()).thenReturn( + WakefulnessLifecycle.WAKEFULNESS_GOING_TO_SLEEP); + when(mDozeParameters.shouldClampToDimBrightness()).thenReturn(false); + + mScreen.transitionTo(UNINITIALIZED, INITIALIZED); + mScreen.transitionTo(INITIALIZED, DOZE); + + assertEquals(mServiceFake.screenBrightnessFloat, DEFAULT_BRIGHTNESS_FLOAT, DELTA); + assertEquals(PowerManager.BRIGHTNESS_DEFAULT, mServiceFake.screenBrightnessInt); + } + + @Test + @RequiresFlagsDisabled(Flags.FLAG_DOZE_BRIGHTNESS_FLOAT) + public void transitionToAodPaused_lightSensorDisabled_Int() { + // GIVEN AOD + mScreen.transitionTo(UNINITIALIZED, INITIALIZED); + mScreen.transitionTo(INITIALIZED, DOZE_AOD); + + // WHEN AOD is paused + mScreen.transitionTo(DOZE_AOD, DOZE_AOD_PAUSING); + mScreen.transitionTo(DOZE_AOD, DOZE_AOD_PAUSED); + waitForSensorManager(); + + // THEN new light events don't update brightness since the light sensor was unregistered + mSensor.sendSensorEvent(1); + assertEquals(mServiceFake.screenBrightnessInt, DEFAULT_BRIGHTNESS_INT); + assertTrue(Float.isNaN(mServiceFake.screenBrightnessFloat)); } @Test - public void transitionToAodPaused_lightSensorDisabled() { + @RequiresFlagsEnabled(Flags.FLAG_DOZE_BRIGHTNESS_FLOAT) + public void transitionToAodPaused_lightSensorDisabled_Float() { // GIVEN AOD mScreen.transitionTo(UNINITIALIZED, INITIALIZED); mScreen.transitionTo(INITIALIZED, DOZE_AOD); @@ -558,11 +1040,13 @@ public class DozeScreenBrightnessTest extends SysuiTestCase { // THEN new light events don't update brightness since the light sensor was unregistered mSensor.sendSensorEvent(1); - assertEquals(mServiceFake.screenBrightness, DEFAULT_BRIGHTNESS); + assertEquals(mServiceFake.screenBrightnessFloat, DEFAULT_BRIGHTNESS_FLOAT, DELTA); + assertEquals(PowerManager.BRIGHTNESS_DEFAULT, mServiceFake.screenBrightnessInt); } @Test - public void transitionFromAodPausedToAod_lightSensorEnabled() { + @RequiresFlagsDisabled(Flags.FLAG_DOZE_BRIGHTNESS_FLOAT) + public void transitionFromAodPausedToAod_lightSensorEnabled_Int() { // GIVEN AOD paused mScreen.transitionTo(UNINITIALIZED, INITIALIZED); mScreen.transitionTo(INITIALIZED, DOZE_AOD); @@ -577,7 +1061,54 @@ public class DozeScreenBrightnessTest extends SysuiTestCase { mSensor.sendSensorEvent(1); // THEN aod brightness is updated - assertEquals(mServiceFake.screenBrightness, 1); + assertEquals(SENSOR_TO_BRIGHTNESS_INT[1], mServiceFake.screenBrightnessInt); + assertTrue(Float.isNaN(mServiceFake.screenBrightnessFloat)); + } + + @Test + @RequiresFlagsEnabled(Flags.FLAG_DOZE_BRIGHTNESS_FLOAT) + public void transitionFromAodPausedToAod_lightSensorEnabled_Float() { + // GIVEN AOD paused + mScreen.transitionTo(UNINITIALIZED, INITIALIZED); + mScreen.transitionTo(INITIALIZED, DOZE_AOD); + mScreen.transitionTo(DOZE_AOD, DOZE_AOD_PAUSING); + mScreen.transitionTo(DOZE_AOD, DOZE_AOD_PAUSED); + + // WHEN device transitions back to AOD + mScreen.transitionTo(DOZE_AOD_PAUSED, DOZE_AOD); + waitForSensorManager(); + + // WHEN there are brightness changes + mSensor.sendSensorEvent(1); + + // THEN aod brightness is updated + assertEquals(SENSOR_TO_BRIGHTNESS_FLOAT[1], mServiceFake.screenBrightnessFloat, DELTA); + assertEquals(PowerManager.BRIGHTNESS_DEFAULT, mServiceFake.screenBrightnessInt); + } + + @Test + @RequiresFlagsEnabled(Flags.FLAG_DOZE_BRIGHTNESS_FLOAT) + public void fallBackToIntIfFloatBrightnessUndefined() { + when(mDisplayManager.getDozeBrightnessSensorValueToBrightness(Display.DEFAULT_DISPLAY)) + .thenReturn(null); + mScreen = new DozeScreenBrightness( + mContext, + mServiceFake, + mSensorManager, + new Optional[]{Optional.of(mSensor.getSensor())}, + mDozeHost, + null /* handler */, + mAlwaysOnDisplayPolicy, + mWakefulnessLifecycle, + mDozeParameters, + mDevicePostureController, + mDozeLog, + mSystemSettings, + mDisplayManager); + mScreen.transitionTo(UNINITIALIZED, INITIALIZED); + + assertEquals(DEFAULT_BRIGHTNESS_INT, mServiceFake.screenBrightnessInt); + assertTrue(Float.isNaN(mServiceFake.screenBrightnessFloat)); } private void waitForSensorManager() { diff --git a/packages/SystemUI/tests/src/com/android/systemui/doze/DozeServiceFake.java b/packages/SystemUI/tests/src/com/android/systemui/doze/DozeServiceFake.java index 928b314197b1..f55c2b77ca0f 100644 --- a/packages/SystemUI/tests/src/com/android/systemui/doze/DozeServiceFake.java +++ b/packages/SystemUI/tests/src/com/android/systemui/doze/DozeServiceFake.java @@ -30,7 +30,8 @@ public class DozeServiceFake implements DozeMachine.Service { public int screenState; public boolean screenStateSet; public boolean requestedWakeup; - public int screenBrightness; + public int screenBrightnessInt; + public float screenBrightnessFloat; public DozeServiceFake() { reset(); @@ -54,7 +55,12 @@ public class DozeServiceFake implements DozeMachine.Service { @Override public void setDozeScreenBrightness(int brightness) { - screenBrightness = brightness; + screenBrightnessInt = brightness; + } + + @Override + public void setDozeScreenBrightnessFloat(float brightness) { + screenBrightnessFloat = brightness; } public void reset() { @@ -62,6 +68,7 @@ public class DozeServiceFake implements DozeMachine.Service { screenState = Display.STATE_UNKNOWN; screenStateSet = false; requestedWakeup = false; - screenBrightness = PowerManager.BRIGHTNESS_DEFAULT; + screenBrightnessInt = PowerManager.BRIGHTNESS_DEFAULT; + screenBrightnessFloat = PowerManager.BRIGHTNESS_INVALID_FLOAT; } } diff --git a/packages/SystemUI/tests/src/com/android/systemui/keyguard/KeyguardViewMediatorTest.java b/packages/SystemUI/tests/src/com/android/systemui/keyguard/KeyguardViewMediatorTest.java index e68a4a57de75..ff6588758066 100644 --- a/packages/SystemUI/tests/src/com/android/systemui/keyguard/KeyguardViewMediatorTest.java +++ b/packages/SystemUI/tests/src/com/android/systemui/keyguard/KeyguardViewMediatorTest.java @@ -70,10 +70,10 @@ import android.view.IRemoteAnimationFinishedCallback; import android.view.RemoteAnimationTarget; import android.view.View; import android.view.ViewRootImpl; -import android.view.WindowManager; import androidx.test.filters.SmallTest; +import com.android.app.viewcapture.ViewCaptureAwareWindowManager; import com.android.internal.foldables.FoldGracePeriodProvider; import com.android.internal.logging.InstanceId; import com.android.internal.logging.UiEventLogger; @@ -111,6 +111,7 @@ import com.android.systemui.shade.ShadeController; import com.android.systemui.shade.ShadeExpansionStateManager; import com.android.systemui.shade.ShadeWindowLogger; import com.android.systemui.shade.domain.interactor.ShadeInteractor; +import com.android.systemui.shade.ui.viewmodel.NotificationShadeWindowModel; import com.android.systemui.statusbar.NotificationShadeDepthController; import com.android.systemui.statusbar.NotificationShadeWindowController; import com.android.systemui.statusbar.SysuiStatusBarStateController; @@ -167,7 +168,7 @@ public class KeyguardViewMediatorTest extends SysuiTestCase { private @Mock BroadcastDispatcher mBroadcastDispatcher; private @Mock DismissCallbackRegistry mDismissCallbackRegistry; private @Mock DumpManager mDumpManager; - private @Mock WindowManager mWindowManager; + private @Mock ViewCaptureAwareWindowManager mWindowManager; private @Mock IActivityManager mActivityManager; private @Mock ConfigurationController mConfigurationController; private @Mock PowerManager mPowerManager; @@ -225,6 +226,7 @@ public class KeyguardViewMediatorTest extends SysuiTestCase { private @Mock DreamViewModel mDreamViewModel; private @Mock CommunalTransitionViewModel mCommunalTransitionViewModel; private @Mock SystemPropertiesHelper mSystemPropertiesHelper; + @Mock private NotificationShadeWindowModel mNotificationShadeWindowModel; private FakeFeatureFlags mFeatureFlags; private final int mDefaultUserId = 100; @@ -272,6 +274,7 @@ public class KeyguardViewMediatorTest extends SysuiTestCase { mShadeWindowLogger, () -> mSelectedUserInteractor, mUserTracker, + mNotificationShadeWindowModel, mKosmos::getCommunalInteractor); mFeatureFlags = new FakeFeatureFlags(); mSetFlagsRule.enableFlags(FLAG_REFACTOR_GET_CURRENT_USER); diff --git a/packages/SystemUI/tests/src/com/android/systemui/lifecycle/RepeatWhenAttachedTest.kt b/packages/SystemUI/tests/src/com/android/systemui/lifecycle/RepeatWhenAttachedTest.kt index afab25092278..d3409c7256fd 100644 --- a/packages/SystemUI/tests/src/com/android/systemui/lifecycle/RepeatWhenAttachedTest.kt +++ b/packages/SystemUI/tests/src/com/android/systemui/lifecycle/RepeatWhenAttachedTest.kt @@ -24,12 +24,14 @@ import androidx.lifecycle.LifecycleOwner import androidx.test.filters.SmallTest import com.android.systemui.SysuiTestCase import com.android.systemui.util.Assert -import com.android.systemui.util.mockito.argumentCaptor import com.google.common.truth.Truth.assertThat import kotlinx.coroutines.CoroutineScope import kotlinx.coroutines.Dispatchers import kotlinx.coroutines.DisposableHandle import kotlinx.coroutines.ExperimentalCoroutinesApi +import kotlinx.coroutines.Job +import kotlinx.coroutines.awaitCancellation +import kotlinx.coroutines.launch import kotlinx.coroutines.test.StandardTestDispatcher import kotlinx.coroutines.test.TestScope import kotlinx.coroutines.test.resetMain @@ -47,6 +49,8 @@ import org.mockito.Mockito.any import org.mockito.Mockito.verify import org.mockito.Mockito.`when` as whenever import org.mockito.junit.MockitoJUnit +import org.mockito.kotlin.KArgumentCaptor +import org.mockito.kotlin.argumentCaptor @OptIn(ExperimentalCoroutinesApi::class) @SmallTest @@ -96,6 +100,14 @@ class RepeatWhenAttachedTest : SysuiTestCase() { } @Test(expected = IllegalStateException::class) + fun repeatWhenAttachedToWindow_enforcesMainThread() = + testScope.runTest { + Assert.setTestThread(null) + + view.repeatWhenAttachedToWindow {} + } + + @Test(expected = IllegalStateException::class) fun repeatWhenAttached_disposeEnforcesMainThread() = testScope.runTest { val disposableHandle = repeatWhenAttached() @@ -120,6 +132,58 @@ class RepeatWhenAttachedTest : SysuiTestCase() { } @Test + fun repeatWhenAttachedToWindow_viewAlreadyAttached_immediatelyRunsBlock() = + testScope.runTest { + whenever(view.isAttachedToWindow).thenReturn(true) + + var innerJob: Job? = null + backgroundScope.launch { + view.repeatWhenAttachedToWindow { innerJob = launch { awaitCancellation() } } + } + runCurrent() + + assertThat(innerJob?.isActive).isEqualTo(true) + } + + @Test + fun repeatWhenAttachedToWindow_viewStartsDetached_runsBlockWhenAttached() = + testScope.runTest { + whenever(view.isAttachedToWindow).thenReturn(false) + var innerJob: Job? = null + backgroundScope.launch { + view.repeatWhenAttachedToWindow { innerJob = launch { awaitCancellation() } } + } + runCurrent() + + assertThat(innerJob?.isActive).isNotEqualTo(true) + + whenever(view.isAttachedToWindow).thenReturn(true) + attachListeners.last().onViewAttachedToWindow(view) + runCurrent() + + assertThat(innerJob?.isActive).isEqualTo(true) + } + + @Test + fun repeatWhenAttachedToWindow_viewGetsDetached_cancelsBlock() = + testScope.runTest { + whenever(view.isAttachedToWindow).thenReturn(true) + var innerJob: Job? = null + backgroundScope.launch { + view.repeatWhenAttachedToWindow { innerJob = launch { awaitCancellation() } } + } + runCurrent() + + assertThat(innerJob?.isActive).isEqualTo(true) + + whenever(view.isAttachedToWindow).thenReturn(false) + attachListeners.last().onViewDetachedFromWindow(view) + runCurrent() + + assertThat(innerJob?.isActive).isNotEqualTo(true) + } + + @Test fun repeatWhenAttached_viewAlreadyAttached_immediatelyRunsBlock() = testScope.runTest { whenever(view.isAttachedToWindow).thenReturn(true) @@ -145,6 +209,65 @@ class RepeatWhenAttachedTest : SysuiTestCase() { } @Test + fun repeatWhenWindowIsVisible_startsAlreadyVisible_immediatelyRunsBlock() = + testScope.runTest { + whenever(view.isAttachedToWindow).thenReturn(true) + whenever(view.windowVisibility).thenReturn(View.VISIBLE) + + var innerJob: Job? = null + backgroundScope.launch { + view.repeatWhenWindowIsVisible { innerJob = launch { awaitCancellation() } } + } + runCurrent() + + assertThat(innerJob?.isActive).isEqualTo(true) + } + + @Test + fun repeatWhenWindowIsVisible_startsInvisible_runsBlockWhenVisible() = + testScope.runTest { + whenever(view.isAttachedToWindow).thenReturn(true) + whenever(view.windowVisibility).thenReturn(View.INVISIBLE) + + var innerJob: Job? = null + backgroundScope.launch { + view.repeatWhenWindowIsVisible { innerJob = launch { awaitCancellation() } } + } + runCurrent() + + assertThat(innerJob?.isActive).isNotEqualTo(true) + + whenever(view.windowVisibility).thenReturn(View.VISIBLE) + argCaptor { verify(viewTreeObserver).addOnWindowVisibilityChangeListener(capture()) } + .forEach { it.onWindowVisibilityChanged(View.VISIBLE) } + runCurrent() + + assertThat(innerJob?.isActive).isEqualTo(true) + } + + @Test + fun repeatWhenWindowIsVisible_becomesInvisible_cancelsBlock() = + testScope.runTest { + whenever(view.isAttachedToWindow).thenReturn(true) + whenever(view.windowVisibility).thenReturn(View.VISIBLE) + + var innerJob: Job? = null + backgroundScope.launch { + view.repeatWhenWindowIsVisible { innerJob = launch { awaitCancellation() } } + } + runCurrent() + + assertThat(innerJob?.isActive).isEqualTo(true) + + whenever(view.windowVisibility).thenReturn(View.INVISIBLE) + argCaptor { verify(viewTreeObserver).addOnWindowVisibilityChangeListener(capture()) } + .forEach { it.onWindowVisibilityChanged(View.INVISIBLE) } + runCurrent() + + assertThat(innerJob?.isActive).isNotEqualTo(true) + } + + @Test fun repeatWhenAttached_startsWithFocusButInvisible_CREATED() = testScope.runTest { whenever(view.isAttachedToWindow).thenReturn(true) @@ -172,6 +295,69 @@ class RepeatWhenAttachedTest : SysuiTestCase() { } @Test + fun repeatWhenWindowHasFocus_startsWithFocus_immediatelyRunsBlock() = + testScope.runTest { + whenever(view.isAttachedToWindow).thenReturn(true) + whenever(view.windowVisibility).thenReturn(View.VISIBLE) + whenever(view.hasWindowFocus()).thenReturn(true) + + var innerJob: Job? = null + backgroundScope.launch { + view.repeatWhenWindowHasFocus { innerJob = launch { awaitCancellation() } } + } + runCurrent() + + assertThat(innerJob?.isActive).isEqualTo(true) + } + + @Test + fun repeatWhenWindowHasFocus_startsWithoutFocus_runsBlockWhenFocused() = + testScope.runTest { + whenever(view.isAttachedToWindow).thenReturn(true) + whenever(view.windowVisibility).thenReturn(View.VISIBLE) + whenever(view.hasWindowFocus()).thenReturn(false) + + var innerJob: Job? = null + backgroundScope.launch { + view.repeatWhenWindowHasFocus { innerJob = launch { awaitCancellation() } } + } + runCurrent() + + assertThat(innerJob?.isActive).isNotEqualTo(true) + + whenever(view.hasWindowFocus()).thenReturn(true) + + argCaptor { verify(viewTreeObserver).addOnWindowFocusChangeListener(capture()) } + .forEach { it.onWindowFocusChanged(true) } + runCurrent() + + assertThat(innerJob?.isActive).isEqualTo(true) + } + + @Test + fun repeatWhenWindowHasFocus_losesFocus_cancelsBlock() = + testScope.runTest { + whenever(view.isAttachedToWindow).thenReturn(true) + whenever(view.windowVisibility).thenReturn(View.VISIBLE) + whenever(view.hasWindowFocus()).thenReturn(true) + + var innerJob: Job? = null + backgroundScope.launch { + view.repeatWhenWindowHasFocus { innerJob = launch { awaitCancellation() } } + } + runCurrent() + + assertThat(innerJob?.isActive).isEqualTo(true) + + whenever(view.hasWindowFocus()).thenReturn(false) + argCaptor { verify(viewTreeObserver).addOnWindowFocusChangeListener(capture()) } + .forEach { it.onWindowFocusChanged(false) } + runCurrent() + + assertThat(innerJob?.isActive).isNotEqualTo(true) + } + + @Test fun repeatWhenAttached_becomesVisibleWithoutFocus_STARTED() = testScope.runTest { whenever(view.isAttachedToWindow).thenReturn(true) @@ -180,7 +366,7 @@ class RepeatWhenAttachedTest : SysuiTestCase() { verify(viewTreeObserver).addOnWindowVisibilityChangeListener(listenerCaptor.capture()) whenever(view.windowVisibility).thenReturn(View.VISIBLE) - listenerCaptor.value.onWindowVisibilityChanged(View.VISIBLE) + listenerCaptor.lastValue.onWindowVisibilityChanged(View.VISIBLE) runCurrent() assertThat(block.invocationCount).isEqualTo(1) @@ -196,7 +382,7 @@ class RepeatWhenAttachedTest : SysuiTestCase() { verify(viewTreeObserver).addOnWindowFocusChangeListener(listenerCaptor.capture()) whenever(view.hasWindowFocus()).thenReturn(true) - listenerCaptor.value.onWindowFocusChanged(true) + listenerCaptor.lastValue.onWindowFocusChanged(true) runCurrent() assertThat(block.invocationCount).isEqualTo(1) @@ -214,9 +400,9 @@ class RepeatWhenAttachedTest : SysuiTestCase() { verify(viewTreeObserver).addOnWindowFocusChangeListener(focusCaptor.capture()) whenever(view.windowVisibility).thenReturn(View.VISIBLE) - visibleCaptor.value.onWindowVisibilityChanged(View.VISIBLE) + visibleCaptor.lastValue.onWindowVisibilityChanged(View.VISIBLE) whenever(view.hasWindowFocus()).thenReturn(true) - focusCaptor.value.onWindowFocusChanged(true) + focusCaptor.lastValue.onWindowFocusChanged(true) runCurrent() assertThat(block.invocationCount).isEqualTo(1) @@ -314,6 +500,7 @@ class RepeatWhenAttachedTest : SysuiTestCase() { val invocations: List<Invocation> = _invocations val invocationCount: Int get() = _invocations.size + val latestLifecycleState: Lifecycle.State get() = _invocations.last().lifecycleState @@ -322,3 +509,9 @@ class RepeatWhenAttachedTest : SysuiTestCase() { } } } + +private inline fun <reified T : Any> argCaptor(block: KArgumentCaptor<T>.() -> Unit) = + argumentCaptor<T>().apply { block() } + +private inline fun <reified T : Any> KArgumentCaptor<T>.forEach(block: (T) -> Unit): Unit = + allValues.forEach(block) diff --git a/packages/SystemUI/tests/src/com/android/systemui/navigationbar/NavigationBarControllerImplTest.java b/packages/SystemUI/tests/src/com/android/systemui/navigationbar/NavigationBarControllerImplTest.java index 196bbb9f2dee..413aa55f4554 100644 --- a/packages/SystemUI/tests/src/com/android/systemui/navigationbar/NavigationBarControllerImplTest.java +++ b/packages/SystemUI/tests/src/com/android/systemui/navigationbar/NavigationBarControllerImplTest.java @@ -307,7 +307,7 @@ public class NavigationBarControllerImplTest extends SysuiTestCase { mNavigationBarController.mIsLargeScreen = false; mNavigationBarController.mIsPhone = true; - assertFalse(mNavigationBarController.supportsTaskbar()); + assertTrue(mNavigationBarController.supportsTaskbar()); } @Test diff --git a/packages/SystemUI/tests/src/com/android/systemui/qs/tileimpl/QSTileViewImplTest.kt b/packages/SystemUI/tests/src/com/android/systemui/qs/tileimpl/QSTileViewImplTest.kt index 988769fe6660..90ffaf19be96 100644 --- a/packages/SystemUI/tests/src/com/android/systemui/qs/tileimpl/QSTileViewImplTest.kt +++ b/packages/SystemUI/tests/src/com/android/systemui/qs/tileimpl/QSTileViewImplTest.kt @@ -25,6 +25,7 @@ import android.text.TextUtils import android.view.ContextThemeWrapper import android.view.View import android.view.accessibility.AccessibilityNodeInfo +import android.widget.Button import android.widget.TextView import androidx.test.ext.junit.runners.AndroidJUnit4 import androidx.test.filters.SmallTest @@ -381,6 +382,47 @@ class QSTileViewImplTest : SysuiTestCase() { } @Test + fun testNonSwitchA11yClass_longClickActionHasCorrectLabel() { + val state = + QSTile.State().apply { + expandedAccessibilityClassName = Button::class.java.name + handlesLongClick = true + } + tileView.changeState(state) + val info = AccessibilityNodeInfo(tileView) + tileView.onInitializeAccessibilityNodeInfo(info) + + assertThat( + info.actionList + .find { + it.id == AccessibilityNodeInfo.AccessibilityAction.ACTION_LONG_CLICK.id + } + ?.label + ) + .isEqualTo(context.getString(R.string.accessibility_long_click_tile)) + } + + @Test + fun testNonSwitchA11yClass_disabledByPolicy_noLongClickAction() { + val state = + QSTile.State().apply { + expandedAccessibilityClassName = Button::class.java.name + handlesLongClick = true + disabledByPolicy = true + } + tileView.changeState(state) + val info = AccessibilityNodeInfo(tileView) + tileView.onInitializeAccessibilityNodeInfo(info) + + assertThat( + info.actionList.find { + it.id == AccessibilityNodeInfo.AccessibilityAction.ACTION_LONG_CLICK.id + } + ) + .isNull() + } + + @Test fun onStateChange_longPressEffectActive_withInvalidDuration_doesNotInitializeEffect() { val state = QSTile.State() // A state that handles longPress diff --git a/packages/SystemUI/tests/src/com/android/systemui/qs/tiles/DndTileTest.kt b/packages/SystemUI/tests/src/com/android/systemui/qs/tiles/DndTileTest.kt index e01744e3576c..6a43a61dad77 100644 --- a/packages/SystemUI/tests/src/com/android/systemui/qs/tiles/DndTileTest.kt +++ b/packages/SystemUI/tests/src/com/android/systemui/qs/tiles/DndTileTest.kt @@ -20,6 +20,7 @@ import android.app.Dialog import android.content.ContextWrapper import android.content.SharedPreferences import android.os.Handler +import android.platform.test.annotations.DisableFlags import android.provider.Settings import android.provider.Settings.Global.ZEN_MODE_NO_INTERRUPTIONS import android.provider.Settings.Global.ZEN_MODE_OFF @@ -61,6 +62,7 @@ import org.mockito.Mockito.`when` as whenever @SmallTest @RunWith(AndroidJUnit4::class) @TestableLooper.RunWithLooper(setAsMainLooper = true) +@DisableFlags(android.app.Flags.FLAG_MODES_UI) class DndTileTest : SysuiTestCase() { companion object { diff --git a/packages/SystemUI/tests/src/com/android/systemui/qs/tiles/ModesTileTest.kt b/packages/SystemUI/tests/src/com/android/systemui/qs/tiles/ModesTileTest.kt index 74d9692d3a6c..a5de7cd0b4db 100644 --- a/packages/SystemUI/tests/src/com/android/systemui/qs/tiles/ModesTileTest.kt +++ b/packages/SystemUI/tests/src/com/android/systemui/qs/tiles/ModesTileTest.kt @@ -47,8 +47,8 @@ import com.android.systemui.util.settings.FakeSettings import com.android.systemui.util.settings.SecureSettings 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.UnconfinedTestDispatcher import kotlinx.coroutines.test.runCurrent import kotlinx.coroutines.test.runTest import org.junit.After @@ -82,9 +82,12 @@ class ModesTileTest : SysuiTestCase() { @Mock private lateinit var dialogDelegate: ModesDialogDelegate + private val testDispatcher = UnconfinedTestDispatcher() + private val testScope = TestScope(testDispatcher) + private val inputHandler = FakeQSTileIntentUserInputHandler() private val zenModeRepository = FakeZenModeRepository() - private val tileDataInteractor = ModesTileDataInteractor(zenModeRepository) + private val tileDataInteractor = ModesTileDataInteractor(zenModeRepository, testDispatcher) private val mapper = ModesTileMapper( context.orCreateTestableResources @@ -96,9 +99,6 @@ class ModesTileTest : SysuiTestCase() { context.theme, ) - private val testDispatcher = StandardTestDispatcher() - private val testScope = TestScope(testDispatcher) - private lateinit var userActionInteractor: ModesTileUserActionInteractor private lateinit var secureSettings: SecureSettings private lateinit var testableLooper: TestableLooper diff --git a/packages/SystemUI/tests/src/com/android/systemui/shade/QuickSettingsControllerImplBaseTest.java b/packages/SystemUI/tests/src/com/android/systemui/shade/QuickSettingsControllerImplBaseTest.java index 06a883c02ac0..b7ce33671492 100644 --- a/packages/SystemUI/tests/src/com/android/systemui/shade/QuickSettingsControllerImplBaseTest.java +++ b/packages/SystemUI/tests/src/com/android/systemui/shade/QuickSettingsControllerImplBaseTest.java @@ -44,7 +44,6 @@ import com.android.systemui.deviceentry.domain.interactor.DeviceEntryUdfpsIntera import com.android.systemui.dump.DumpManager; import com.android.systemui.flags.FeatureFlags; import com.android.systemui.fragments.FragmentHostManager; -import com.android.systemui.keyguard.data.repository.FakeCommandQueue; import com.android.systemui.keyguard.data.repository.FakeKeyguardRepository; import com.android.systemui.keyguard.domain.interactor.KeyguardInteractor; import com.android.systemui.keyguard.domain.interactor.KeyguardTransitionInteractor; @@ -190,7 +189,6 @@ public class QuickSettingsControllerImplBaseTest extends SysuiTestCase { mKosmos.getKeyguardTransitionInteractor(); KeyguardInteractor keyguardInteractor = new KeyguardInteractor( mKeyguardRepository, - new FakeCommandQueue(), powerInteractor, new FakeKeyguardBouncerRepository(), new ConfigurationInteractor(configurationRepository), diff --git a/packages/SystemUI/tests/src/com/android/systemui/shared/notifications/data/repository/NotificationSettingsRepositoryTest.kt b/packages/SystemUI/tests/src/com/android/systemui/shared/notifications/data/repository/NotificationSettingsRepositoryTest.kt index 69cc9d5d971a..35f2e6e433fa 100644 --- a/packages/SystemUI/tests/src/com/android/systemui/shared/notifications/data/repository/NotificationSettingsRepositoryTest.kt +++ b/packages/SystemUI/tests/src/com/android/systemui/shared/notifications/data/repository/NotificationSettingsRepositoryTest.kt @@ -17,11 +17,13 @@ package com.android.systemui.shared.notifications.data.repository import android.provider.Settings +import android.provider.Settings.Secure.ZEN_DURATION_FOREVER import androidx.test.ext.junit.runners.AndroidJUnit4 import androidx.test.filters.SmallTest import com.android.systemui.SysuiTestCase import com.android.systemui.coroutines.collectLastValue import com.android.systemui.shared.settings.data.repository.FakeSecureSettingsRepository +import com.android.systemui.shared.settings.data.repository.FakeSystemSettingsRepository import com.google.common.truth.Truth.assertThat import kotlinx.coroutines.test.StandardTestDispatcher import kotlinx.coroutines.test.TestScope @@ -38,23 +40,26 @@ class NotificationSettingsRepositoryTest : SysuiTestCase() { private lateinit var testScope: TestScope private lateinit var secureSettingsRepository: FakeSecureSettingsRepository + private lateinit var systemSettingsRepository: FakeSystemSettingsRepository @Before fun setUp() { val testDispatcher = StandardTestDispatcher() testScope = TestScope(testDispatcher) secureSettingsRepository = FakeSecureSettingsRepository() + systemSettingsRepository = FakeSystemSettingsRepository() underTest = NotificationSettingsRepository( - scope = testScope.backgroundScope, + backgroundScope = testScope.backgroundScope, backgroundDispatcher = testDispatcher, secureSettingsRepository = secureSettingsRepository, + systemSettingsRepository = systemSettingsRepository, ) } @Test - fun testGetIsShowNotificationsOnLockscreenEnabled() = + fun getIsShowNotificationsOnLockscreenEnabled() = testScope.runTest { val showNotifs by collectLastValue(underTest.isShowNotificationsOnLockScreenEnabled()) @@ -72,7 +77,7 @@ class NotificationSettingsRepositoryTest : SysuiTestCase() { } @Test - fun testSetIsShowNotificationsOnLockscreenEnabled() = + fun setIsShowNotificationsOnLockscreenEnabled() = testScope.runTest { val showNotifs by collectLastValue(underTest.isShowNotificationsOnLockScreenEnabled()) @@ -84,7 +89,7 @@ class NotificationSettingsRepositoryTest : SysuiTestCase() { } @Test - fun testGetIsNotificationHistoryEnabled() = + fun getIsNotificationHistoryEnabled() = testScope.runTest { val historyEnabled by collectLastValue(underTest.isNotificationHistoryEnabled) @@ -100,4 +105,40 @@ class NotificationSettingsRepositoryTest : SysuiTestCase() { ) assertThat(historyEnabled).isEqualTo(false) } + + @Test + fun testGetIsCooldownEnabled() = + testScope.runTest { + val cooldownEnabled by collectLastValue(underTest.isCooldownEnabled) + + systemSettingsRepository.setInt( + name = Settings.System.NOTIFICATION_COOLDOWN_ENABLED, + value = 1, + ) + assertThat(cooldownEnabled).isEqualTo(true) + + systemSettingsRepository.setInt( + name = Settings.System.NOTIFICATION_COOLDOWN_ENABLED, + value = 0, + ) + assertThat(cooldownEnabled).isEqualTo(false) + } + + @Test + fun zenDuration() = + testScope.runTest { + val zenDuration by collectLastValue(underTest.zenDuration) + + secureSettingsRepository.setInt( + name = Settings.Secure.ZEN_DURATION, + value = 60, + ) + assertThat(zenDuration).isEqualTo(60) + + secureSettingsRepository.setInt( + name = Settings.Secure.ZEN_DURATION, + value = ZEN_DURATION_FOREVER, + ) + assertThat(zenDuration).isEqualTo(ZEN_DURATION_FOREVER) + } } diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/collection/coordinator/SensitiveContentCoordinatorTest.kt b/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/collection/coordinator/SensitiveContentCoordinatorTest.kt index 05057278f7ca..689fc7cb647b 100644 --- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/collection/coordinator/SensitiveContentCoordinatorTest.kt +++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/collection/coordinator/SensitiveContentCoordinatorTest.kt @@ -28,7 +28,11 @@ import androidx.test.filters.SmallTest import com.android.keyguard.KeyguardUpdateMonitor import com.android.server.notification.Flags.FLAG_SCREENSHARE_NOTIFICATION_HIDING import com.android.systemui.SysuiTestCase +import com.android.systemui.dagger.qualifiers.Application +import com.android.systemui.deviceentry.domain.interactor.DeviceEntryInteractor +import com.android.systemui.kosmos.applicationCoroutineScope import com.android.systemui.plugins.statusbar.StatusBarStateController +import com.android.systemui.scene.domain.interactor.SceneInteractor import com.android.systemui.statusbar.NotificationLockscreenUserManager import com.android.systemui.statusbar.RankingBuilder import com.android.systemui.statusbar.StatusBarState @@ -45,6 +49,7 @@ import com.android.systemui.statusbar.notification.collection.listbuilder.plugga import com.android.systemui.statusbar.notification.row.ExpandableNotificationRow import com.android.systemui.statusbar.policy.KeyguardStateController import com.android.systemui.statusbar.policy.SensitiveNotificationProtectionController +import com.android.systemui.testKosmos import com.android.systemui.user.domain.interactor.SelectedUserInteractor import com.android.systemui.util.mockito.any import com.android.systemui.util.mockito.eq @@ -52,6 +57,7 @@ import com.android.systemui.util.mockito.mock import com.android.systemui.util.mockito.withArgCaptor import dagger.BindsInstance import dagger.Component +import kotlinx.coroutines.CoroutineScope import org.junit.Assert.assertFalse import org.junit.Assert.assertTrue import org.junit.Test @@ -64,6 +70,8 @@ import org.mockito.Mockito.`when` as whenever @RunWith(AndroidJUnit4::class) class SensitiveContentCoordinatorTest : SysuiTestCase() { + val kosmos = testKosmos() + val dynamicPrivacyController: DynamicPrivacyController = mock() val lockscreenUserManager: NotificationLockscreenUserManager = mock() val pipeline: NotifPipeline = mock() @@ -73,6 +81,8 @@ class SensitiveContentCoordinatorTest : SysuiTestCase() { val mSelectedUserInteractor: SelectedUserInteractor = mock() val sensitiveNotificationProtectionController: SensitiveNotificationProtectionController = mock() + val deviceEntryInteractor: DeviceEntryInteractor = mock() + val sceneInteractor: SceneInteractor = mock() val coordinator: SensitiveContentCoordinator = DaggerTestSensitiveContentCoordinatorComponent.factory() @@ -83,7 +93,10 @@ class SensitiveContentCoordinatorTest : SysuiTestCase() { statusBarStateController, keyguardStateController, mSelectedUserInteractor, - sensitiveNotificationProtectionController + sensitiveNotificationProtectionController, + deviceEntryInteractor, + sceneInteractor, + kosmos.applicationCoroutineScope, ) .coordinator @@ -136,8 +149,7 @@ class SensitiveContentCoordinatorTest : SysuiTestCase() { @Test @EnableFlags(FLAG_SCREENSHARE_NOTIFICATION_HIDING) fun screenshareSecretFilter_sensitiveInctive_noFiltersSecret() { - whenever(sensitiveNotificationProtectionController.isSensitiveStateActive) - .thenReturn(false) + whenever(sensitiveNotificationProtectionController.isSensitiveStateActive).thenReturn(false) coordinator.attach(pipeline) val filter = withArgCaptor<NotifFilter> { verify(pipeline).addFinalizeFilter(capture()) } @@ -683,10 +695,11 @@ class SensitiveContentCoordinatorTest : SysuiTestCase() { val mockSbn: StatusBarNotification = mock<StatusBarNotification>().apply { whenever(user).thenReturn(mockUserHandle) } val mockRow: ExpandableNotificationRow = mock<ExpandableNotificationRow>() - val mockEntry = mock<NotificationEntry>().apply { - whenever(sbn).thenReturn(mockSbn) - whenever(row).thenReturn(mockRow) - } + val mockEntry = + mock<NotificationEntry>().apply { + whenever(sbn).thenReturn(mockSbn) + whenever(row).thenReturn(mockRow) + } whenever(lockscreenUserManager.needsRedaction(mockEntry)).thenReturn(needsRedaction) whenever(mockEntry.rowExists()).thenReturn(true) return object : ListEntry("key", 0) { @@ -737,6 +750,9 @@ interface TestSensitiveContentCoordinatorComponent { @BindsInstance selectedUserInteractor: SelectedUserInteractor, @BindsInstance sensitiveNotificationProtectionController: SensitiveNotificationProtectionController, + @BindsInstance deviceEntryInteractor: DeviceEntryInteractor, + @BindsInstance sceneInteractor: SceneInteractor, + @BindsInstance @Application scope: CoroutineScope, ): TestSensitiveContentCoordinatorComponent } } diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/interruption/VisualInterruptionDecisionProviderImplTest.kt b/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/interruption/VisualInterruptionDecisionProviderImplTest.kt index a7f36c317f3b..f9509d2d394d 100644 --- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/interruption/VisualInterruptionDecisionProviderImplTest.kt +++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/interruption/VisualInterruptionDecisionProviderImplTest.kt @@ -66,7 +66,8 @@ class VisualInterruptionDecisionProviderImplTest : VisualInterruptionDecisionPro packageManager, Optional.of(bubbles), context, - notificationManager + notificationManager, + settingsInteractor ) } @@ -101,7 +102,7 @@ class VisualInterruptionDecisionProviderImplTest : VisualInterruptionDecisionPro whenever(avalancheProvider.startTime).thenReturn(whenAgo(10)) val avalancheSuppressor = AvalancheSuppressor( - avalancheProvider, systemClock, systemSettings, packageManager, + avalancheProvider, systemClock, settingsInteractor, packageManager, uiEventLogger, context, notificationManager ) avalancheSuppressor.hasSeenEdu = false @@ -125,7 +126,7 @@ class VisualInterruptionDecisionProviderImplTest : VisualInterruptionDecisionPro whenever(avalancheProvider.startTime).thenReturn(whenAgo(10)) val avalancheSuppressor = AvalancheSuppressor( - avalancheProvider, systemClock, systemSettings, packageManager, + avalancheProvider, systemClock, settingsInteractor, packageManager, uiEventLogger, context, notificationManager ) avalancheSuppressor.hasSeenEdu = true @@ -147,7 +148,7 @@ class VisualInterruptionDecisionProviderImplTest : VisualInterruptionDecisionPro avalancheProvider.startTime = whenAgo(10) withFilter( - AvalancheSuppressor(avalancheProvider, systemClock, systemSettings, packageManager, + AvalancheSuppressor(avalancheProvider, systemClock, settingsInteractor, packageManager, uiEventLogger, context, notificationManager) ) { ensurePeekState() @@ -167,7 +168,7 @@ class VisualInterruptionDecisionProviderImplTest : VisualInterruptionDecisionPro avalancheProvider.startTime = whenAgo(10) withFilter( - AvalancheSuppressor(avalancheProvider, systemClock, systemSettings, packageManager, + AvalancheSuppressor(avalancheProvider, systemClock, settingsInteractor, packageManager, uiEventLogger, context, notificationManager) ) { ensurePeekState() @@ -187,7 +188,7 @@ class VisualInterruptionDecisionProviderImplTest : VisualInterruptionDecisionPro avalancheProvider.startTime = whenAgo(10) withFilter( - AvalancheSuppressor(avalancheProvider, systemClock, systemSettings, packageManager, + AvalancheSuppressor(avalancheProvider, systemClock, settingsInteractor, packageManager, uiEventLogger, context, notificationManager) ) { ensurePeekState() @@ -205,7 +206,7 @@ class VisualInterruptionDecisionProviderImplTest : VisualInterruptionDecisionPro avalancheProvider.startTime = whenAgo(10) withFilter( - AvalancheSuppressor(avalancheProvider, systemClock, systemSettings, packageManager, + AvalancheSuppressor(avalancheProvider, systemClock, settingsInteractor, packageManager, uiEventLogger, context, notificationManager) ) { ensurePeekState() @@ -223,7 +224,7 @@ class VisualInterruptionDecisionProviderImplTest : VisualInterruptionDecisionPro avalancheProvider.startTime = whenAgo(10) withFilter( - AvalancheSuppressor(avalancheProvider, systemClock, systemSettings, packageManager, + AvalancheSuppressor(avalancheProvider, systemClock, settingsInteractor, packageManager, uiEventLogger, context, notificationManager) ) { ensurePeekState() @@ -241,7 +242,7 @@ class VisualInterruptionDecisionProviderImplTest : VisualInterruptionDecisionPro avalancheProvider.startTime = whenAgo(10) withFilter( - AvalancheSuppressor(avalancheProvider, systemClock, systemSettings, packageManager, + AvalancheSuppressor(avalancheProvider, systemClock, settingsInteractor, packageManager, uiEventLogger, context, notificationManager) ) { ensurePeekState() @@ -259,7 +260,7 @@ class VisualInterruptionDecisionProviderImplTest : VisualInterruptionDecisionPro avalancheProvider.startTime = whenAgo(10) withFilter( - AvalancheSuppressor(avalancheProvider, systemClock, systemSettings, packageManager, + AvalancheSuppressor(avalancheProvider, systemClock, settingsInteractor, packageManager, uiEventLogger, context, notificationManager) ) { assertFsiNotSuppressed() @@ -271,7 +272,7 @@ class VisualInterruptionDecisionProviderImplTest : VisualInterruptionDecisionPro avalancheProvider.startTime = whenAgo(10) withFilter( - AvalancheSuppressor(avalancheProvider, systemClock, systemSettings, packageManager, + AvalancheSuppressor(avalancheProvider, systemClock, settingsInteractor, packageManager, uiEventLogger, context, notificationManager) ) { ensurePeekState() @@ -300,7 +301,7 @@ class VisualInterruptionDecisionProviderImplTest : VisualInterruptionDecisionPro setAllowedEmergencyPkg(true) withFilter( - AvalancheSuppressor(avalancheProvider, systemClock, systemSettings, packageManager, + AvalancheSuppressor(avalancheProvider, systemClock, settingsInteractor, packageManager, uiEventLogger, context, notificationManager) ) { ensurePeekState() diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/interruption/VisualInterruptionDecisionProviderTestBase.kt b/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/interruption/VisualInterruptionDecisionProviderTestBase.kt index d5ab62b43866..9d3d9c156238 100644 --- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/interruption/VisualInterruptionDecisionProviderTestBase.kt +++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/interruption/VisualInterruptionDecisionProviderTestBase.kt @@ -61,6 +61,7 @@ import com.android.systemui.log.LogcatEchoTracker import com.android.systemui.log.core.LogLevel import com.android.systemui.res.R import com.android.systemui.settings.FakeUserTracker +import com.android.systemui.shared.notifications.domain.interactor.NotificationSettingsInteractor import com.android.systemui.statusbar.FakeStatusBarStateController import com.android.systemui.statusbar.NotificationEntryHelper.modifyRanking import com.android.systemui.statusbar.StatusBarState.KEYGUARD @@ -88,6 +89,7 @@ import com.android.systemui.utils.os.FakeHandler import com.android.wm.shell.bubbles.Bubbles import junit.framework.Assert.assertFalse import junit.framework.Assert.assertTrue +import kotlinx.coroutines.flow.MutableStateFlow import org.junit.Assert.assertEquals import org.junit.Before import org.junit.Test @@ -134,6 +136,7 @@ abstract class VisualInterruptionDecisionProviderTestBase : SysuiTestCase() { protected val avalancheProvider: AvalancheProvider = mock() protected val bubbles: Bubbles = mock() lateinit var systemSettings: SystemSettings + protected val settingsInteractor: NotificationSettingsInteractor = mock() protected val packageManager: PackageManager = mock() protected val notificationManager: NotificationManager = mock() protected abstract val provider: VisualInterruptionDecisionProvider @@ -164,7 +167,7 @@ abstract class VisualInterruptionDecisionProviderTestBase : SysuiTestCase() { userTracker.set(listOf(user), /* currentUserIndex = */ 0) systemSettings = FakeSettings() whenever(bubbles.canShowBubbleNotification()).thenReturn(true) - + whenever(settingsInteractor.isCooldownEnabled).thenReturn(MutableStateFlow(true)) provider.start() } diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/interruption/VisualInterruptionDecisionProviderTestUtil.kt b/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/interruption/VisualInterruptionDecisionProviderTestUtil.kt index f4cebd7d5d3f..7fd9c9fbdd6b 100644 --- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/interruption/VisualInterruptionDecisionProviderTestUtil.kt +++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/interruption/VisualInterruptionDecisionProviderTestUtil.kt @@ -25,6 +25,7 @@ import com.android.internal.logging.UiEventLogger import com.android.systemui.dagger.qualifiers.Main import com.android.systemui.plugins.statusbar.StatusBarStateController import com.android.systemui.settings.UserTracker +import com.android.systemui.shared.notifications.domain.interactor.NotificationSettingsInteractor import com.android.systemui.statusbar.notification.NotifPipelineFlags import com.android.systemui.statusbar.policy.BatteryController import com.android.systemui.statusbar.policy.DeviceProvisionedController @@ -61,7 +62,8 @@ object VisualInterruptionDecisionProviderTestUtil { packageManager: PackageManager, bubbles: Optional<Bubbles>, context: Context, - notificationManager: NotificationManager + notificationManager: NotificationManager, + settingsInteractor: NotificationSettingsInteractor ): VisualInterruptionDecisionProvider { return if (VisualInterruptionRefactor.isEnabled) { VisualInterruptionDecisionProviderImpl( @@ -85,7 +87,8 @@ object VisualInterruptionDecisionProviderTestUtil { packageManager, bubbles, context, - notificationManager + notificationManager, + settingsInteractor ) } else { NotificationInterruptStateProviderWrapper( diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/stack/NotificationStackScrollLayoutControllerTest.java b/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/stack/NotificationStackScrollLayoutControllerTest.java index c36a046532bd..3df4a677b9e5 100644 --- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/stack/NotificationStackScrollLayoutControllerTest.java +++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/stack/NotificationStackScrollLayoutControllerTest.java @@ -20,6 +20,7 @@ import static com.android.server.notification.Flags.FLAG_SCREENSHARE_NOTIFICATIO import static com.android.systemui.log.LogBufferHelperKt.logcatLogBuffer; import static com.android.systemui.statusbar.StatusBarState.KEYGUARD; import static com.android.systemui.statusbar.StatusBarState.SHADE; +import static com.android.systemui.statusbar.notification.row.NotificationRowContentBinder.FLAG_CONTENT_VIEW_ALL; import static com.android.systemui.statusbar.notification.stack.NotificationStackScrollLayout.ROWS_ALL; import static kotlinx.coroutines.flow.FlowKt.emptyFlow; @@ -96,9 +97,12 @@ import com.android.systemui.statusbar.notification.footer.shared.FooterViewRefac import com.android.systemui.statusbar.notification.init.NotificationsController; import com.android.systemui.statusbar.notification.row.ExpandableNotificationRow; import com.android.systemui.statusbar.notification.row.NotificationGutsManager; +import com.android.systemui.statusbar.notification.row.NotificationTestHelper; +import com.android.systemui.statusbar.notification.shared.GroupHunAnimationFix; import com.android.systemui.statusbar.notification.stack.NotificationStackScrollLayoutController.NotificationPanelEvent; import com.android.systemui.statusbar.notification.stack.NotificationSwipeHelper.NotificationCallback; import com.android.systemui.statusbar.notification.stack.ui.viewbinder.NotificationListViewBinder; +import com.android.systemui.statusbar.phone.HeadsUpAppearanceController; import com.android.systemui.statusbar.phone.HeadsUpTouchHelper; import com.android.systemui.statusbar.phone.KeyguardBypassController; import com.android.systemui.statusbar.policy.ConfigurationController; @@ -192,6 +196,8 @@ public class NotificationStackScrollLayoutControllerTest extends SysuiTestCase { private NotificationStackScrollLayoutController mController; + private NotificationTestHelper mNotificationTestHelper; + @Before public void setUp() { allowTestableLooperAsMainThread(); @@ -199,6 +205,11 @@ public class NotificationStackScrollLayoutControllerTest extends SysuiTestCase { when(mNotificationSwipeHelperBuilder.build()).thenReturn(mNotificationSwipeHelper); when(mKeyguardTransitionRepo.getTransitions()).thenReturn(emptyFlow()); + mNotificationTestHelper = new NotificationTestHelper( + mContext, + mDependency, + TestableLooper.get(this)); + mNotificationTestHelper.setDefaultInflationFlags(FLAG_CONTENT_VIEW_ALL); } @Test @@ -222,6 +233,42 @@ public class NotificationStackScrollLayoutControllerTest extends SysuiTestCase { } @Test + @EnableFlags(GroupHunAnimationFix.FLAG_NAME) + public void changeHeadsUpAnimatingAwayToTrue_onEntryAnimatingAwayEndedNotCalled() + throws Exception { + // Before: bind an ExpandableNotificationRow, + initController(/* viewIsAttached= */ true); + mController.setHeadsUpAppearanceController(mock(HeadsUpAppearanceController.class)); + NotificationListContainer listContainer = mController.getNotificationListContainer(); + ExpandableNotificationRow row = mNotificationTestHelper.createRow(); + listContainer.bindRow(row); + + // When: call setHeadsUpAnimatingAway to change set mHeadsupDisappearRunning to true + row.setHeadsUpAnimatingAway(true); + + // Then: mHeadsUpManager.onEntryAnimatingAwayEnded is not called + verify(mHeadsUpManager, never()).onEntryAnimatingAwayEnded(row.getEntry()); + } + + @Test + @EnableFlags(GroupHunAnimationFix.FLAG_NAME) + public void changeHeadsUpAnimatingAwayToFalse_onEntryAnimatingAwayEndedCalled() + throws Exception { + // Before: bind an ExpandableNotificationRow, set its mHeadsupDisappearRunning to true + initController(/* viewIsAttached= */ true); + mController.setHeadsUpAppearanceController(mock(HeadsUpAppearanceController.class)); + NotificationListContainer listContainer = mController.getNotificationListContainer(); + ExpandableNotificationRow row = mNotificationTestHelper.createRow(); + listContainer.bindRow(row); + row.setHeadsUpAnimatingAway(true); + + // When: call setHeadsUpAnimatingAway to change set mHeadsupDisappearRunning to false + row.setHeadsUpAnimatingAway(false); + + // Then: mHeadsUpManager.onEntryAnimatingAwayEnded is called + verify(mHeadsUpManager).onEntryAnimatingAwayEnded(row.getEntry()); + } + @Test public void testOnDensityOrFontScaleChanged_reInflatesFooterViews() { initController(/* viewIsAttached= */ true); diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/stack/domain/interactor/HideNotificationsInteractorTest.kt b/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/stack/domain/interactor/HideNotificationsInteractorTest.kt index e46906fb5192..476252737454 100644 --- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/stack/domain/interactor/HideNotificationsInteractorTest.kt +++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/stack/domain/interactor/HideNotificationsInteractorTest.kt @@ -66,7 +66,8 @@ open class HideNotificationsInteractorTest : SysuiTestCase() { repository = powerRepository, falsingCollector = mock(), screenOffAnimationController = mock(), - statusBarStateController = mock() + statusBarStateController = mock(), + cameraGestureHelper = mock(), ) private val configurationRepository = diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/CentralSurfacesCommandQueueCallbacksTest.java b/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/CentralSurfacesCommandQueueCallbacksTest.java index 5e5586d0f94f..d9e94953e757 100644 --- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/CentralSurfacesCommandQueueCallbacksTest.java +++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/CentralSurfacesCommandQueueCallbacksTest.java @@ -42,6 +42,7 @@ import com.android.systemui.SysuiTestCase; import com.android.systemui.assist.AssistManager; import com.android.systemui.emergency.EmergencyGestureModule.EmergencyGestureIntentFactory; import com.android.systemui.keyguard.WakefulnessLifecycle; +import com.android.systemui.keyguard.domain.interactor.KeyguardInteractor; import com.android.systemui.plugins.ActivityStarter; import com.android.systemui.qs.QSHost; import com.android.systemui.recents.ScreenPinningRequest; @@ -103,6 +104,7 @@ public class CentralSurfacesCommandQueueCallbacksTest extends SysuiTestCase { @Mock private QSHost mQSHost; @Mock private ActivityStarter mActivityStarter; @Mock private EmergencyGestureIntentFactory mEmergencyGestureIntentFactory; + @Mock private KeyguardInteractor mKeyguardInteractor; CentralSurfacesCommandQueueCallbacks mSbcqCallbacks; @@ -140,6 +142,7 @@ public class CentralSurfacesCommandQueueCallbacksTest extends SysuiTestCase { mUserTracker, mQSHost, mActivityStarter, + mKeyguardInteractor, mEmergencyGestureIntentFactory); when(mUserTracker.getUserHandle()).thenReturn( diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/CentralSurfacesImplTest.java b/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/CentralSurfacesImplTest.java index d2540a64bd79..bd9cccd3458a 100644 --- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/CentralSurfacesImplTest.java +++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/CentralSurfacesImplTest.java @@ -150,6 +150,7 @@ import com.android.systemui.shade.ShadeController; import com.android.systemui.shade.ShadeControllerImpl; import com.android.systemui.shade.ShadeExpansionStateManager; import com.android.systemui.shade.ShadeLogger; +import com.android.systemui.shared.notifications.domain.interactor.NotificationSettingsInteractor; import com.android.systemui.statusbar.CommandQueue; import com.android.systemui.statusbar.KeyboardShortcutListSearch; import com.android.systemui.statusbar.KeyboardShortcuts; @@ -343,7 +344,7 @@ public class CentralSurfacesImplTest extends SysuiTestCase { @Mock private NotificationManager mNotificationManager; @Mock private GlanceableHubContainerController mGlanceableHubContainerController; @Mock private EmergencyGestureIntentFactory mEmergencyGestureIntentFactory; - + @Mock private NotificationSettingsInteractor mNotificationSettingsInteractor; private ShadeController mShadeController; private final FakeSystemClock mFakeSystemClock = new FakeSystemClock(); private final FakeGlobalSettings mFakeGlobalSettings = new FakeGlobalSettings(); @@ -403,7 +404,8 @@ public class CentralSurfacesImplTest extends SysuiTestCase { mPackageManager, Optional.of(mBubbles), mContext, - mNotificationManager); + mNotificationManager, + mNotificationSettingsInteractor); mVisualInterruptionDecisionProvider.start(); mContext.addMockSystemService(TrustManager.class, mock(TrustManager.class)); diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/KeyguardClockPositionAlgorithmTest.java b/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/KeyguardClockPositionAlgorithmTest.java index cf87afbbff34..7f33c23e8abc 100644 --- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/KeyguardClockPositionAlgorithmTest.java +++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/KeyguardClockPositionAlgorithmTest.java @@ -299,27 +299,7 @@ public class KeyguardClockPositionAlgorithmTest extends SysuiTestCase { } @Test - @DisableFlags(Flags.FLAG_CENTRALIZED_STATUS_BAR_HEIGHT_FIX) - public void notifPaddingMakesUpToFullMarginInSplitShade_refactorFlagOff_usesResource() { - int keyguardSplitShadeTopMargin = 100; - int largeScreenHeaderHeightResource = 70; - when(mResources.getDimensionPixelSize(R.dimen.keyguard_split_shade_top_margin)) - .thenReturn(keyguardSplitShadeTopMargin); - when(mResources.getDimensionPixelSize(R.dimen.large_screen_shade_header_height)) - .thenReturn(largeScreenHeaderHeightResource); - mClockPositionAlgorithm.loadDimens(mContext, mResources); - givenLockScreen(); - mIsSplitShade = true; - // WHEN the position algorithm is run - positionClock(); - // THEN the notif padding makes up lacking margin (margin - header height). - int expectedPadding = keyguardSplitShadeTopMargin - largeScreenHeaderHeightResource; - assertThat(mClockPosition.stackScrollerPadding).isEqualTo(expectedPadding); - } - - @Test - @EnableFlags(Flags.FLAG_CENTRALIZED_STATUS_BAR_HEIGHT_FIX) - public void notifPaddingMakesUpToFullMarginInSplitShade_refactorFlagOn_usesHelper() { + public void notifPaddingMakesUpToFullMarginInSplitShade_usesHelper() { int keyguardSplitShadeTopMargin = 100; int largeScreenHeaderHeightHelper = 50; int largeScreenHeaderHeightResource = 70; diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/StatusBarKeyguardViewManagerTest.java b/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/StatusBarKeyguardViewManagerTest.java index af5e60e9cd01..9b611057c059 100644 --- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/StatusBarKeyguardViewManagerTest.java +++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/StatusBarKeyguardViewManagerTest.java @@ -1068,7 +1068,7 @@ public class StatusBarKeyguardViewManagerTest extends SysuiTestCase { public void testShowBouncerOrKeyguard_needsFullScreen() { when(mKeyguardSecurityModel.getSecurityMode(anyInt())).thenReturn( KeyguardSecurityModel.SecurityMode.SimPin); - mStatusBarKeyguardViewManager.showBouncerOrKeyguard(false); + mStatusBarKeyguardViewManager.showBouncerOrKeyguard(false, false); verify(mCentralSurfaces).hideKeyguard(); verify(mPrimaryBouncerInteractor).show(true); } @@ -1084,7 +1084,7 @@ public class StatusBarKeyguardViewManagerTest extends SysuiTestCase { .thenReturn(KeyguardState.LOCKSCREEN); reset(mCentralSurfaces); - mStatusBarKeyguardViewManager.showBouncerOrKeyguard(false); + mStatusBarKeyguardViewManager.showBouncerOrKeyguard(false, false); verify(mPrimaryBouncerInteractor).show(true); verify(mCentralSurfaces).showKeyguard(); } @@ -1092,11 +1092,26 @@ public class StatusBarKeyguardViewManagerTest extends SysuiTestCase { @Test @DisableSceneContainer public void testShowBouncerOrKeyguard_needsFullScreen_bouncerAlreadyShowing() { + boolean isFalsingReset = false; when(mKeyguardSecurityModel.getSecurityMode(anyInt())).thenReturn( KeyguardSecurityModel.SecurityMode.SimPin); when(mPrimaryBouncerInteractor.isFullyShowing()).thenReturn(true); - mStatusBarKeyguardViewManager.showBouncerOrKeyguard(false); + mStatusBarKeyguardViewManager.showBouncerOrKeyguard(false, isFalsingReset); verify(mCentralSurfaces, never()).hideKeyguard(); + verify(mPrimaryBouncerInteractor).show(true); + } + + @Test + @DisableSceneContainer + public void testShowBouncerOrKeyguard_needsFullScreen_bouncerAlreadyShowing_onFalsing() { + boolean isFalsingReset = true; + when(mKeyguardSecurityModel.getSecurityMode(anyInt())).thenReturn( + KeyguardSecurityModel.SecurityMode.SimPin); + when(mPrimaryBouncerInteractor.isFullyShowing()).thenReturn(true); + mStatusBarKeyguardViewManager.showBouncerOrKeyguard(false, isFalsingReset); + verify(mCentralSurfaces, never()).hideKeyguard(); + + // Do not refresh the full screen bouncer if the call is from falsing verify(mPrimaryBouncerInteractor, never()).show(true); } diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/pipeline/satellite/data/prod/DeviceBasedSatelliteRepositoryImplTest.kt b/packages/SystemUI/tests/src/com/android/systemui/statusbar/pipeline/satellite/data/prod/DeviceBasedSatelliteRepositoryImplTest.kt index 73ac6e3573d6..af4f647923a7 100644 --- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/pipeline/satellite/data/prod/DeviceBasedSatelliteRepositoryImplTest.kt +++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/pipeline/satellite/data/prod/DeviceBasedSatelliteRepositoryImplTest.kt @@ -22,6 +22,7 @@ import android.telephony.TelephonyCallback import android.telephony.TelephonyManager import android.telephony.satellite.NtnSignalStrength import android.telephony.satellite.NtnSignalStrengthCallback +import android.telephony.satellite.SatelliteCommunicationAllowedStateCallback import android.telephony.satellite.SatelliteManager import android.telephony.satellite.SatelliteManager.SATELLITE_MODEM_STATE_CONNECTED import android.telephony.satellite.SatelliteManager.SATELLITE_MODEM_STATE_DATAGRAM_RETRYING @@ -44,7 +45,6 @@ import com.android.systemui.coroutines.collectLastValue import com.android.systemui.log.core.FakeLogBuffer import com.android.systemui.statusbar.pipeline.mobile.data.repository.prod.MobileTelephonyHelpers import com.android.systemui.statusbar.pipeline.satellite.data.prod.DeviceBasedSatelliteRepositoryImpl.Companion.MIN_UPTIME -import com.android.systemui.statusbar.pipeline.satellite.data.prod.DeviceBasedSatelliteRepositoryImpl.Companion.POLLING_INTERVAL_MS import com.android.systemui.statusbar.pipeline.satellite.shared.model.SatelliteConnectionState import com.android.systemui.util.mockito.any import com.android.systemui.util.mockito.whenever @@ -54,11 +54,8 @@ import com.google.common.truth.Truth.assertThat import java.util.Optional import kotlin.test.Test import kotlinx.coroutines.ExperimentalCoroutinesApi -import kotlinx.coroutines.flow.launchIn -import kotlinx.coroutines.flow.onEach import kotlinx.coroutines.test.StandardTestDispatcher import kotlinx.coroutines.test.TestScope -import kotlinx.coroutines.test.advanceTimeBy import kotlinx.coroutines.test.runCurrent import kotlinx.coroutines.test.runTest import org.junit.Before @@ -71,6 +68,7 @@ import org.mockito.Mockito.never import org.mockito.Mockito.times import org.mockito.Mockito.verify import org.mockito.MockitoAnnotations +import org.mockito.kotlin.doThrow @Suppress("EXPERIMENTAL_IS_NOT_ENABLED") @OptIn(ExperimentalCoroutinesApi::class) @@ -186,149 +184,83 @@ class DeviceBasedSatelliteRepositoryImplTest : SysuiTestCase() { } @Test - fun isSatelliteAllowed_readsSatelliteManagerState_enabled() = + fun isSatelliteAllowed_listensToSatelliteManagerCallback() = testScope.runTest { setupDefaultRepo() - // GIVEN satellite is allowed in this location - val allowed = true - - doAnswer { - val receiver = it.arguments[1] as OutcomeReceiver<Boolean, SatelliteException> - receiver.onResult(allowed) - null - } - .`when`(satelliteManager) - .requestIsCommunicationAllowedForCurrentLocation( - any(), - any<OutcomeReceiver<Boolean, SatelliteException>>() - ) val latest by collectLastValue(underTest.isSatelliteAllowedForCurrentLocation) + runCurrent() - assertThat(latest).isTrue() - } - - @Test - fun isSatelliteAllowed_readsSatelliteManagerState_disabled() = - testScope.runTest { - setupDefaultRepo() - // GIVEN satellite is not allowed in this location - val allowed = false - - doAnswer { - val receiver = it.arguments[1] as OutcomeReceiver<Boolean, SatelliteException> - receiver.onResult(allowed) - null + val callback = + withArgCaptor<SatelliteCommunicationAllowedStateCallback> { + verify(satelliteManager) + .registerForCommunicationAllowedStateChanged(any(), capture()) } - .`when`(satelliteManager) - .requestIsCommunicationAllowedForCurrentLocation( - any(), - any<OutcomeReceiver<Boolean, SatelliteException>>() - ) - val latest by collectLastValue(underTest.isSatelliteAllowedForCurrentLocation) + // WHEN satellite manager says it's not available + callback.onSatelliteCommunicationAllowedStateChanged(false) + // THEN it's not! assertThat(latest).isFalse() + + // WHEN satellite manager says it's changed to available + callback.onSatelliteCommunicationAllowedStateChanged(true) + + // THEN it is! + assertThat(latest).isTrue() } @Test - fun isSatelliteAllowed_pollsOnTimeout() = + fun isSatelliteAllowed_falseWhenErrorOccurs() = testScope.runTest { setupDefaultRepo() - // GIVEN satellite is not allowed in this location - var allowed = false - doAnswer { - val receiver = it.arguments[1] as OutcomeReceiver<Boolean, SatelliteException> - receiver.onResult(allowed) - null - } + // GIVEN SatelliteManager gon' throw exceptions when we ask to register the callback + doThrow(RuntimeException("Test exception")) .`when`(satelliteManager) - .requestIsCommunicationAllowedForCurrentLocation( - any(), - any<OutcomeReceiver<Boolean, SatelliteException>>() - ) + .registerForCommunicationAllowedStateChanged(any(), any()) + // WHEN the latest value is requested (and thus causes an exception to be thrown) val latest by collectLastValue(underTest.isSatelliteAllowedForCurrentLocation) + // THEN the value is just false, and we didn't crash! assertThat(latest).isFalse() - - // WHEN satellite becomes enabled - allowed = true - - // WHEN the timeout has not yet been reached - advanceTimeBy(POLLING_INTERVAL_MS / 2) - - // THEN the value is still false - assertThat(latest).isFalse() - - // WHEN time advances beyond the polling interval - advanceTimeBy(POLLING_INTERVAL_MS / 2 + 1) - - // THEN then new value is emitted - assertThat(latest).isTrue() } @Test - fun isSatelliteAllowed_pollingRestartsWhenCollectionRestarts() = + fun isSatelliteAllowed_reRegistersOnTelephonyProcessCrash() = testScope.runTest { setupDefaultRepo() - // Use the old school launch/cancel so we can simulate subscribers arriving and leaving - - var latest: Boolean? = false - var job = - underTest.isSatelliteAllowedForCurrentLocation.onEach { latest = it }.launchIn(this) - - // GIVEN satellite is not allowed in this location - var allowed = false + val latest by collectLastValue(underTest.isSatelliteAllowedForCurrentLocation) + runCurrent() - doAnswer { - val receiver = it.arguments[1] as OutcomeReceiver<Boolean, SatelliteException> - receiver.onResult(allowed) - null + val callback = + withArgCaptor<SatelliteCommunicationAllowedStateCallback> { + verify(satelliteManager) + .registerForCommunicationAllowedStateChanged(any(), capture()) } - .`when`(satelliteManager) - .requestIsCommunicationAllowedForCurrentLocation( - any(), - any<OutcomeReceiver<Boolean, SatelliteException>>() - ) - assertThat(latest).isFalse() - - // WHEN satellite becomes enabled - allowed = true - - // WHEN the job is restarted - advanceTimeBy(POLLING_INTERVAL_MS / 2) + val telephonyCallback = + MobileTelephonyHelpers.getTelephonyCallbackForType< + TelephonyCallback.RadioPowerStateListener + >( + telephonyManager + ) - job.cancel() - job = - underTest.isSatelliteAllowedForCurrentLocation.onEach { latest = it }.launchIn(this) + // GIVEN satellite is currently provisioned + callback.onSatelliteCommunicationAllowedStateChanged(true) - // THEN the value is re-fetched assertThat(latest).isTrue() - job.cancel() - } - - @Test - fun isSatelliteAllowed_falseWhenErrorOccurs() = - testScope.runTest { - setupDefaultRepo() - doAnswer { - val receiver = it.arguments[1] as OutcomeReceiver<Boolean, SatelliteException> - receiver.onError(SatelliteException(1 /* unused */)) - null - } - .`when`(satelliteManager) - .requestIsCommunicationAllowedForCurrentLocation( - any(), - any<OutcomeReceiver<Boolean, SatelliteException>>() - ) - - val latest by collectLastValue(underTest.isSatelliteAllowedForCurrentLocation) + // WHEN a crash event happens (detected by radio state change) + telephonyCallback.onRadioPowerStateChanged(TelephonyManager.RADIO_POWER_ON) + runCurrent() + telephonyCallback.onRadioPowerStateChanged(TelephonyManager.RADIO_POWER_OFF) + runCurrent() - assertThat(latest).isFalse() + // THEN listener is re-registered + verify(satelliteManager, times(2)) + .registerForCommunicationAllowedStateChanged(any(), any()) } @Test @@ -363,24 +295,21 @@ class DeviceBasedSatelliteRepositoryImplTest : SysuiTestCase() { testScope.runTest { // GIVEN satellite is supported on device doAnswer { - val callback: OutcomeReceiver<Boolean, SatelliteException> = - it.getArgument(1) as OutcomeReceiver<Boolean, SatelliteException> - callback.onResult(true) - } + val callback: OutcomeReceiver<Boolean, SatelliteException> = + it.getArgument(1) as OutcomeReceiver<Boolean, SatelliteException> + callback.onResult(true) + } .whenever(satelliteManager) .requestIsSupported(any(), any()) // GIVEN satellite returns an error when asked if provisioned doAnswer { - val receiver = it.arguments[1] as OutcomeReceiver<Boolean, SatelliteException> - receiver.onError(SatelliteException(SATELLITE_RESULT_ERROR)) - null - } + val receiver = it.arguments[1] as OutcomeReceiver<Boolean, SatelliteException> + receiver.onError(SatelliteException(SATELLITE_RESULT_ERROR)) + null + } .whenever(satelliteManager) - .requestIsProvisioned( - any(), - any<OutcomeReceiver<Boolean, SatelliteException>>() - ) + .requestIsProvisioned(any(), any<OutcomeReceiver<Boolean, SatelliteException>>()) // GIVEN we've been up long enough to start querying systemClock.setUptimeMillis(Process.getStartUptimeMillis() + MIN_UPTIME) @@ -409,10 +338,10 @@ class DeviceBasedSatelliteRepositoryImplTest : SysuiTestCase() { testScope.runTest { // GIVEN satellite is supported on device doAnswer { - val callback: OutcomeReceiver<Boolean, SatelliteException> = - it.getArgument(1) as OutcomeReceiver<Boolean, SatelliteException> - callback.onResult(true) - } + val callback: OutcomeReceiver<Boolean, SatelliteException> = + it.getArgument(1) as OutcomeReceiver<Boolean, SatelliteException> + callback.onResult(true) + } .whenever(satelliteManager) .requestIsSupported(any(), any()) @@ -779,10 +708,10 @@ class DeviceBasedSatelliteRepositoryImplTest : SysuiTestCase() { .requestIsSupported(any(), any()) doAnswer { - val callback: OutcomeReceiver<Boolean, SatelliteException> = - it.getArgument(1) as OutcomeReceiver<Boolean, SatelliteException> - callback.onResult(initialSatelliteIsProvisioned) - } + val callback: OutcomeReceiver<Boolean, SatelliteException> = + it.getArgument(1) as OutcomeReceiver<Boolean, SatelliteException> + callback.onResult(initialSatelliteIsProvisioned) + } .whenever(satelliteManager) .requestIsProvisioned(any(), any()) diff --git a/packages/SystemUI/tests/src/com/android/systemui/touchpad/data/repository/TouchpadRepositoryTest.kt b/packages/SystemUI/tests/src/com/android/systemui/touchpad/data/repository/TouchpadRepositoryTest.kt new file mode 100644 index 000000000000..3783af554969 --- /dev/null +++ b/packages/SystemUI/tests/src/com/android/systemui/touchpad/data/repository/TouchpadRepositoryTest.kt @@ -0,0 +1,184 @@ +/* + * Copyright (C) 2024 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.android.systemui.touchpad.data.repository + +import android.hardware.input.FakeInputManager +import android.hardware.input.InputManager.InputDeviceListener +import android.hardware.input.fakeInputManager +import android.testing.TestableLooper +import android.view.InputDevice +import androidx.test.ext.junit.runners.AndroidJUnit4 +import androidx.test.filters.SmallTest +import com.android.systemui.SysuiTestCase +import com.android.systemui.coroutines.collectLastValue +import com.android.systemui.inputdevice.data.repository.InputDeviceRepository +import com.android.systemui.testKosmos +import com.android.systemui.utils.os.FakeHandler +import com.google.common.truth.Truth.assertThat +import kotlinx.coroutines.CoroutineDispatcher +import kotlinx.coroutines.flow.first +import kotlinx.coroutines.test.StandardTestDispatcher +import kotlinx.coroutines.test.TestScope +import kotlinx.coroutines.test.runTest +import org.junit.Before +import org.junit.Test +import org.junit.runner.RunWith +import org.mockito.ArgumentCaptor +import org.mockito.ArgumentMatchers.eq +import org.mockito.Captor +import org.mockito.Mockito +import org.mockito.MockitoAnnotations +import org.mockito.kotlin.anyOrNull +import org.mockito.kotlin.whenever + +@SmallTest +@TestableLooper.RunWithLooper +@RunWith(AndroidJUnit4::class) +class TouchpadRepositoryTest : SysuiTestCase() { + + @Captor private lateinit var deviceListenerCaptor: ArgumentCaptor<InputDeviceListener> + private lateinit var fakeInputManager: FakeInputManager + + private lateinit var underTest: TouchpadRepository + private lateinit var dispatcher: CoroutineDispatcher + private lateinit var inputDeviceRepo: InputDeviceRepository + private lateinit var testScope: TestScope + + @Before + fun setUp() { + MockitoAnnotations.initMocks(this) + fakeInputManager = testKosmos().fakeInputManager + dispatcher = StandardTestDispatcher() + testScope = TestScope(dispatcher) + val handler = FakeHandler(TestableLooper.get(this).looper) + inputDeviceRepo = + InputDeviceRepository(handler, testScope.backgroundScope, fakeInputManager.inputManager) + underTest = + TouchpadRepositoryImpl(dispatcher, fakeInputManager.inputManager, inputDeviceRepo) + } + + @Test + fun emitsDisconnected_ifNothingIsConnected() = + testScope.runTest { + val initialState = underTest.isAnyTouchpadConnected.first() + assertThat(initialState).isFalse() + } + + @Test + fun emitsConnected_ifTouchpadAlreadyConnectedAtTheStart() = + testScope.runTest { + fakeInputManager.addDevice(TOUCHPAD_ID, TOUCHPAD) + val initialValue = underTest.isAnyTouchpadConnected.first() + assertThat(initialValue).isTrue() + } + + @Test + fun emitsConnected_whenNewTouchpadConnects() = + testScope.runTest { + captureDeviceListener() + val isTouchpadConnected by collectLastValue(underTest.isAnyTouchpadConnected) + + fakeInputManager.addDevice(TOUCHPAD_ID, TOUCHPAD) + + assertThat(isTouchpadConnected).isTrue() + } + + @Test + fun emitsDisconnected_whenDeviceWithIdDoesNotExist() = + testScope.runTest { + captureDeviceListener() + val isTouchpadConnected by collectLastValue(underTest.isAnyTouchpadConnected) + whenever(fakeInputManager.inputManager.getInputDevice(eq(NULL_DEVICE_ID))) + .thenReturn(null) + fakeInputManager.addDevice(NULL_DEVICE_ID, InputDevice.SOURCE_UNKNOWN) + assertThat(isTouchpadConnected).isFalse() + } + + @Test + fun emitsDisconnected_whenTouchpadDisconnects() = + testScope.runTest { + captureDeviceListener() + val isTouchpadConnected by collectLastValue(underTest.isAnyTouchpadConnected) + + fakeInputManager.addDevice(TOUCHPAD_ID, TOUCHPAD) + assertThat(isTouchpadConnected).isTrue() + + fakeInputManager.removeDevice(TOUCHPAD_ID) + assertThat(isTouchpadConnected).isFalse() + } + + private suspend fun captureDeviceListener() { + underTest.isAnyTouchpadConnected.first() + Mockito.verify(fakeInputManager.inputManager) + .registerInputDeviceListener(deviceListenerCaptor.capture(), anyOrNull()) + fakeInputManager.registerInputDeviceListener(deviceListenerCaptor.value) + } + + @Test + fun emitsDisconnected_whenNonTouchpadConnects() = + testScope.runTest { + captureDeviceListener() + val isTouchpadConnected by collectLastValue(underTest.isAnyTouchpadConnected) + + fakeInputManager.addDevice(NON_TOUCHPAD_ID, InputDevice.SOURCE_KEYBOARD) + assertThat(isTouchpadConnected).isFalse() + } + + @Test + fun emitsDisconnected_whenTouchpadDisconnectsAndWasAlreadyConnectedAtTheStart() = + testScope.runTest { + captureDeviceListener() + val isTouchpadConnected by collectLastValue(underTest.isAnyTouchpadConnected) + + fakeInputManager.removeDevice(TOUCHPAD_ID) + assertThat(isTouchpadConnected).isFalse() + } + + @Test + fun emitsConnected_whenAnotherDeviceDisconnects() = + testScope.runTest { + captureDeviceListener() + val isTouchpadConnected by collectLastValue(underTest.isAnyTouchpadConnected) + + fakeInputManager.addDevice(TOUCHPAD_ID, TOUCHPAD) + fakeInputManager.removeDevice(NON_TOUCHPAD_ID) + + assertThat(isTouchpadConnected).isTrue() + } + + @Test + fun emitsConnected_whenOneTouchpadDisconnectsButAnotherRemainsConnected() = + testScope.runTest { + captureDeviceListener() + val isTouchpadConnected by collectLastValue(underTest.isAnyTouchpadConnected) + + fakeInputManager.addDevice(TOUCHPAD_ID, TOUCHPAD) + fakeInputManager.addDevice(ANOTHER_TOUCHPAD_ID, TOUCHPAD) + fakeInputManager.removeDevice(TOUCHPAD_ID) + + assertThat(isTouchpadConnected).isTrue() + } + + private companion object { + private const val TOUCHPAD_ID = 1 + private const val NON_TOUCHPAD_ID = 2 + private const val ANOTHER_TOUCHPAD_ID = 3 + private const val NULL_DEVICE_ID = 4 + + private const val TOUCHPAD = InputDevice.SOURCE_TOUCHPAD + } +} diff --git a/packages/SystemUI/tests/src/com/android/systemui/touchpad/tutorial/ui/gesture/BackGestureMonitorTest.kt b/packages/SystemUI/tests/src/com/android/systemui/touchpad/tutorial/ui/gesture/BackGestureMonitorTest.kt index cf0db7b51676..8875b84055d8 100644 --- a/packages/SystemUI/tests/src/com/android/systemui/touchpad/tutorial/ui/gesture/BackGestureMonitorTest.kt +++ b/packages/SystemUI/tests/src/com/android/systemui/touchpad/tutorial/ui/gesture/BackGestureMonitorTest.kt @@ -28,6 +28,9 @@ import android.view.MotionEvent.CLASSIFICATION_TWO_FINGER_SWIPE import androidx.test.ext.junit.runners.AndroidJUnit4 import androidx.test.filters.SmallTest import com.android.systemui.SysuiTestCase +import com.android.systemui.touchpad.tutorial.ui.gesture.GestureState.FINISHED +import com.android.systemui.touchpad.tutorial.ui.gesture.GestureState.IN_PROGRESS +import com.android.systemui.touchpad.tutorial.ui.gesture.GestureState.NOT_STARTED import com.google.common.truth.Truth.assertThat import org.junit.Test import org.junit.runner.RunWith @@ -36,16 +39,19 @@ import org.junit.runner.RunWith @RunWith(AndroidJUnit4::class) class BackGestureMonitorTest : SysuiTestCase() { - private var gestureDoneWasCalled = false - private val gestureDoneCallback = { gestureDoneWasCalled = true } - private val gestureMonitor = BackGestureMonitor(SWIPE_DISTANCE.toInt(), gestureDoneCallback) + private var gestureState = NOT_STARTED + private val gestureMonitor = + BackGestureMonitor( + gestureDistanceThresholdPx = SWIPE_DISTANCE.toInt(), + gestureStateChangedCallback = { gestureState = it } + ) companion object { const val SWIPE_DISTANCE = 100f } @Test - fun triggersGestureDoneForThreeFingerGestureRight() { + fun triggersGestureFinishedForThreeFingerGestureRight() { val events = listOf( threeFingerEvent(ACTION_DOWN, x = 0f, y = 0f), @@ -59,11 +65,11 @@ class BackGestureMonitorTest : SysuiTestCase() { events.forEach { gestureMonitor.processTouchpadEvent(it) } - assertThat(gestureDoneWasCalled).isTrue() + assertThat(gestureState).isEqualTo(FINISHED) } @Test - fun triggersGestureDoneForThreeFingerGestureLeft() { + fun triggersGestureFinishedForThreeFingerGestureLeft() { val events = listOf( threeFingerEvent(ACTION_DOWN, x = SWIPE_DISTANCE, y = 0f), @@ -77,7 +83,21 @@ class BackGestureMonitorTest : SysuiTestCase() { events.forEach { gestureMonitor.processTouchpadEvent(it) } - assertThat(gestureDoneWasCalled).isTrue() + assertThat(gestureState).isEqualTo(FINISHED) + } + + @Test + fun triggersGestureProgressForThreeFingerGestureStarted() { + val events = + listOf( + threeFingerEvent(ACTION_DOWN, x = SWIPE_DISTANCE, y = 0f), + threeFingerEvent(ACTION_POINTER_DOWN, x = SWIPE_DISTANCE, y = 0f), + threeFingerEvent(ACTION_POINTER_DOWN, x = SWIPE_DISTANCE, y = 0f), + ) + + events.forEach { gestureMonitor.processTouchpadEvent(it) } + + assertThat(gestureState).isEqualTo(IN_PROGRESS) } private fun threeFingerEvent(action: Int, x: Float, y: Float): MotionEvent { @@ -91,7 +111,7 @@ class BackGestureMonitorTest : SysuiTestCase() { } @Test - fun doesntTriggerGestureDone_onThreeFingersSwipeUp() { + fun doesntTriggerGestureFinished_onThreeFingersSwipeUp() { val events = listOf( threeFingerEvent(ACTION_DOWN, x = 0f, y = 0f), @@ -105,11 +125,11 @@ class BackGestureMonitorTest : SysuiTestCase() { events.forEach { gestureMonitor.processTouchpadEvent(it) } - assertThat(gestureDoneWasCalled).isFalse() + assertThat(gestureState).isEqualTo(NOT_STARTED) } @Test - fun doesntTriggerGestureDone_onTwoFingersSwipe() { + fun doesntTriggerGestureFinished_onTwoFingersSwipe() { fun twoFingerEvent(action: Int, x: Float, y: Float) = motionEvent( action = action, @@ -127,11 +147,11 @@ class BackGestureMonitorTest : SysuiTestCase() { events.forEach { gestureMonitor.processTouchpadEvent(it) } - assertThat(gestureDoneWasCalled).isFalse() + assertThat(gestureState).isEqualTo(NOT_STARTED) } @Test - fun doesntTriggerGestureDone_onFourFingersSwipe() { + fun doesntTriggerGestureFinished_onFourFingersSwipe() { fun fourFingerEvent(action: Int, x: Float, y: Float) = motionEvent( action = action, @@ -155,6 +175,6 @@ class BackGestureMonitorTest : SysuiTestCase() { events.forEach { gestureMonitor.processTouchpadEvent(it) } - assertThat(gestureDoneWasCalled).isFalse() + assertThat(gestureState).isEqualTo(NOT_STARTED) } } diff --git a/packages/SystemUI/tests/src/com/android/systemui/touchpad/tutorial/ui/gesture/TouchpadGestureHandlerTest.kt b/packages/SystemUI/tests/src/com/android/systemui/touchpad/tutorial/ui/gesture/TouchpadGestureHandlerTest.kt index 769f264f0870..dc4d5f674479 100644 --- a/packages/SystemUI/tests/src/com/android/systemui/touchpad/tutorial/ui/gesture/TouchpadGestureHandlerTest.kt +++ b/packages/SystemUI/tests/src/com/android/systemui/touchpad/tutorial/ui/gesture/TouchpadGestureHandlerTest.kt @@ -32,6 +32,8 @@ import android.view.MotionEvent.TOOL_TYPE_MOUSE import androidx.test.ext.junit.runners.AndroidJUnit4 import androidx.test.filters.SmallTest import com.android.systemui.SysuiTestCase +import com.android.systemui.touchpad.tutorial.ui.gesture.GestureState.FINISHED +import com.android.systemui.touchpad.tutorial.ui.gesture.GestureState.NOT_STARTED import com.android.systemui.touchpad.tutorial.ui.gesture.TouchpadGesture.BACK import com.google.common.truth.Truth.assertThat import org.junit.Test @@ -41,8 +43,8 @@ import org.junit.runner.RunWith @RunWith(AndroidJUnit4::class) class TouchpadGestureHandlerTest : SysuiTestCase() { - private var gestureDone = false - private val handler = TouchpadGestureHandler(BACK, SWIPE_DISTANCE) { gestureDone = true } + private var gestureState = NOT_STARTED + private val handler = TouchpadGestureHandler(BACK, SWIPE_DISTANCE) { gestureState = it } companion object { const val SWIPE_DISTANCE = 100 @@ -84,7 +86,7 @@ class TouchpadGestureHandlerTest : SysuiTestCase() { fun triggersGestureDoneForThreeFingerGesture() { backGestureEvents().forEach { handler.onMotionEvent(it) } - assertThat(gestureDone).isTrue() + assertThat(gestureState).isEqualTo(FINISHED) } private fun backGestureEvents(): List<MotionEvent> { diff --git a/packages/SystemUI/tests/src/com/android/systemui/util/settings/SettingsProxyTest.kt b/packages/SystemUI/tests/src/com/android/systemui/util/settings/SettingsProxyTest.kt index 5ac61102fa99..b0acd0386870 100644 --- a/packages/SystemUI/tests/src/com/android/systemui/util/settings/SettingsProxyTest.kt +++ b/packages/SystemUI/tests/src/com/android/systemui/util/settings/SettingsProxyTest.kt @@ -275,6 +275,18 @@ class SettingsProxyTest : SysuiTestCase() { } @Test + fun getInt_keyMalformed_returnDefaultValue() { + mSettings.putString(TEST_SETTING, "nan") + assertThat(mSettings.getInt(TEST_SETTING, 5)).isEqualTo(5) + } + + @Test + fun getInt_keyMalformed_throwException() { + mSettings.putString(TEST_SETTING, "nan") + assertThrows(SettingNotFoundException::class.java) { mSettings.getInt(TEST_SETTING) } + } + + @Test fun getBool_keyPresent_returnValidValue() { mSettings.putBool(TEST_SETTING, true) assertThat(mSettings.getBool(TEST_SETTING)).isTrue() @@ -323,6 +335,18 @@ class SettingsProxyTest : SysuiTestCase() { } @Test + fun getLong_keyMalformed_throwException() { + mSettings.putString(TEST_SETTING, "nan") + assertThrows(SettingNotFoundException::class.java) { mSettings.getLong(TEST_SETTING) } + } + + @Test + fun getLong_keyMalformed_returnDefaultValue() { + mSettings.putString(TEST_SETTING, "nan") + assertThat(mSettings.getLong(TEST_SETTING, 2L)).isEqualTo(2L) + } + + @Test fun getFloat_keyPresent_returnValidValue() { mSettings.putFloat(TEST_SETTING, 2.5F) assertThat(mSettings.getFloat(TEST_SETTING)).isEqualTo(2.5F) @@ -346,6 +370,18 @@ class SettingsProxyTest : SysuiTestCase() { assertThat(mSettings.getFloat(TEST_SETTING, 2.5F)).isEqualTo(2.5F) } + @Test + fun getFloat_keyMalformed_throwException() { + mSettings.putString(TEST_SETTING, "nan") + assertThrows(SettingNotFoundException::class.java) { mSettings.getFloat(TEST_SETTING) } + } + + @Test + fun getFloat_keyMalformed_returnDefaultValue() { + mSettings.putString(TEST_SETTING, "nan") + assertThat(mSettings.getFloat(TEST_SETTING, 2.5F)).isEqualTo(2.5F) + } + private class FakeSettingsProxy(val testDispatcher: CoroutineDispatcher) : SettingsProxy { private val mContentResolver = mock(ContentResolver::class.java) diff --git a/packages/SystemUI/tests/src/com/android/systemui/util/settings/UserSettingsProxyTest.kt b/packages/SystemUI/tests/src/com/android/systemui/util/settings/UserSettingsProxyTest.kt index 5f7420d5a16b..ead9939c1dd7 100644 --- a/packages/SystemUI/tests/src/com/android/systemui/util/settings/UserSettingsProxyTest.kt +++ b/packages/SystemUI/tests/src/com/android/systemui/util/settings/UserSettingsProxyTest.kt @@ -23,6 +23,7 @@ import android.net.Uri import android.os.Handler import android.os.Looper import android.provider.Settings +import android.provider.Settings.SettingNotFoundException import android.testing.TestableLooper import androidx.test.ext.junit.runners.AndroidJUnit4 import androidx.test.filters.SmallTest @@ -433,6 +434,18 @@ class UserSettingsProxyTest : SysuiTestCase() { } @Test + fun getInt_keyMalformed_returnDefaultValue() { + mSettings.putString(TEST_SETTING, "nan") + assertThat(mSettings.getInt(TEST_SETTING, 5)).isEqualTo(5) + } + + @Test + fun getInt_keyMalformed_throwException() { + mSettings.putString(TEST_SETTING, "nan") + assertThrows(SettingNotFoundException::class.java) { mSettings.getInt(TEST_SETTING) } + } + + @Test fun getIntForUser_multipleUsers__validResult() { mSettings.putIntForUser(TEST_SETTING, 1, MAIN_USER_ID) mSettings.putIntForUser(TEST_SETTING, 2, SECONDARY_USER_ID) @@ -501,6 +514,18 @@ class UserSettingsProxyTest : SysuiTestCase() { } @Test + fun getLong_keyMalformed_throwException() { + mSettings.putString(TEST_SETTING, "nan") + assertThrows(SettingNotFoundException::class.java) { mSettings.getLong(TEST_SETTING) } + } + + @Test + fun getLong_keyMalformed_returnDefaultValue() { + mSettings.putString(TEST_SETTING, "nan") + assertThat(mSettings.getLong(TEST_SETTING, 2L)).isEqualTo(2L) + } + + @Test fun getLongForUser_multipleUsers__validResult() { mSettings.putLongForUser(TEST_SETTING, 1L, MAIN_USER_ID) mSettings.putLongForUser(TEST_SETTING, 2L, SECONDARY_USER_ID) @@ -535,6 +560,18 @@ class UserSettingsProxyTest : SysuiTestCase() { } @Test + fun getFloat_keyMalformed_throwException() { + mSettings.putString(TEST_SETTING, "nan") + assertThrows(SettingNotFoundException::class.java) { mSettings.getFloat(TEST_SETTING) } + } + + @Test + fun getFloat_keyMalformed_returnDefaultValue() { + mSettings.putString(TEST_SETTING, "nan") + assertThat(mSettings.getFloat(TEST_SETTING, 2.5F)).isEqualTo(2.5F) + } + + @Test fun getFloatForUser_multipleUsers__validResult() { mSettings.putFloatForUser(TEST_SETTING, 1F, MAIN_USER_ID) mSettings.putFloatForUser(TEST_SETTING, 2F, SECONDARY_USER_ID) diff --git a/packages/SystemUI/tests/src/com/android/systemui/volume/CsdWarningDialogTest.java b/packages/SystemUI/tests/src/com/android/systemui/volume/CsdWarningDialogTest.java index 49aedccde258..bebf1cfa86e7 100644 --- a/packages/SystemUI/tests/src/com/android/systemui/volume/CsdWarningDialogTest.java +++ b/packages/SystemUI/tests/src/com/android/systemui/volume/CsdWarningDialogTest.java @@ -36,7 +36,6 @@ import android.content.pm.ResolveInfo; import android.media.AudioManager; import android.platform.test.annotations.EnableFlags; import android.testing.TestableLooper; -import android.util.Pair; import androidx.test.ext.junit.runners.AndroidJUnit4; import androidx.test.filters.SmallTest; @@ -70,6 +69,8 @@ public class CsdWarningDialogTest extends SysuiTestCase { private CsdWarningDialog mDialog; private static final String DISMISS_CSD_NOTIFICATION = "com.android.systemui.volume.DISMISS_CSD_NOTIFICATION"; + private final Optional<ImmutableList<CsdWarningAction>> mEmptyActions = + Optional.of(ImmutableList.of()); @Before public void setup() { @@ -87,7 +88,7 @@ public class CsdWarningDialogTest extends SysuiTestCase { // instantiate directly instead of via factory; we don't want executor to be @Background mDialog = new CsdWarningDialog(CSD_WARNING_DOSE_REACHED_1X, mContext, mAudioManager, mNotificationManager, executor, null, - Optional.of(ImmutableList.of(new Pair("", new Intent()))), + mEmptyActions, mFakeBroadcastDispatcher); mDialog.show(); @@ -104,7 +105,7 @@ public class CsdWarningDialogTest extends SysuiTestCase { FakeExecutor executor = new FakeExecutor(new FakeSystemClock()); mDialog = new CsdWarningDialog(CSD_WARNING_DOSE_REPEATED_5X, mContext, mAudioManager, mNotificationManager, executor, null, - Optional.of(ImmutableList.of(new Pair("", new Intent()))), + mEmptyActions, mFakeBroadcastDispatcher); mDialog.show(); @@ -121,7 +122,7 @@ public class CsdWarningDialogTest extends SysuiTestCase { .setPackage(mContext.getPackageName()); mDialog = new CsdWarningDialog(CSD_WARNING_DOSE_REPEATED_5X, mContext, mAudioManager, mNotificationManager, executor, null, - Optional.of(ImmutableList.of(new Pair("Undo", undoIntent))), + Optional.of(ImmutableList.of(new CsdWarningAction("Undo", undoIntent, false))), mFakeBroadcastDispatcher); when(mAudioManager.getStreamVolume(AudioManager.STREAM_MUSIC)).thenReturn(25); @@ -148,7 +149,7 @@ public class CsdWarningDialogTest extends SysuiTestCase { .setPackage(mContext.getPackageName()); mDialog = new CsdWarningDialog(CSD_WARNING_DOSE_REPEATED_5X, mContext, mAudioManager, mNotificationManager, executor, null, - Optional.of(ImmutableList.of(new Pair("Undo", undoIntent))), + Optional.of(ImmutableList.of(new CsdWarningAction("Undo", undoIntent, false))), mFakeBroadcastDispatcher); Intent dismissIntent = new Intent(DISMISS_CSD_NOTIFICATION) .setPackage(mContext.getPackageName()); diff --git a/packages/SystemUI/tests/src/com/android/systemui/volume/VolumeDialogControllerImplTest.java b/packages/SystemUI/tests/src/com/android/systemui/volume/VolumeDialogControllerImplTest.java index 3f5dc82ec5cb..8b7d921a1c5b 100644 --- a/packages/SystemUI/tests/src/com/android/systemui/volume/VolumeDialogControllerImplTest.java +++ b/packages/SystemUI/tests/src/com/android/systemui/volume/VolumeDialogControllerImplTest.java @@ -252,7 +252,6 @@ public class VolumeDialogControllerImplTest extends SysuiTestCase { } @Test - @EnableFlags(Flags.FLAG_VOLUME_DIALOG_AUDIO_SHARING_FIX) public void handleAudioSharingStreamVolumeChanges_updateState() { ArgumentCaptor<VolumeDialogController.State> stateCaptor = ArgumentCaptor.forClass(VolumeDialogController.State.class); diff --git a/packages/SystemUI/tests/src/com/android/systemui/volume/VolumeDialogImplTest.java b/packages/SystemUI/tests/src/com/android/systemui/volume/VolumeDialogImplTest.java index b5cbf598bd05..caa177908db0 100644 --- a/packages/SystemUI/tests/src/com/android/systemui/volume/VolumeDialogImplTest.java +++ b/packages/SystemUI/tests/src/com/android/systemui/volume/VolumeDialogImplTest.java @@ -44,7 +44,6 @@ import static org.mockito.Mockito.verify; import static org.mockito.Mockito.when; import android.app.KeyguardManager; -import android.content.Intent; import android.content.res.Configuration; import android.graphics.Bitmap; import android.graphics.Canvas; @@ -57,7 +56,6 @@ import android.platform.test.annotations.EnableFlags; import android.provider.Settings; import android.testing.TestableLooper; import android.util.Log; -import android.util.Pair; import android.view.Gravity; import android.view.InputDevice; import android.view.MotionEvent; @@ -166,7 +164,7 @@ public class VolumeDialogImplTest extends SysuiTestCase { new CsdWarningDialog.Factory() { @Override public CsdWarningDialog create(int warningType, Runnable onCleanup, - Optional<ImmutableList<Pair<String, Intent>>> actionIntents) { + Optional<ImmutableList<CsdWarningAction>> actionIntents) { return mCsdWarningDialog; } }; diff --git a/packages/SystemUI/tests/src/com/android/systemui/wmshell/BubblesTest.java b/packages/SystemUI/tests/src/com/android/systemui/wmshell/BubblesTest.java index 60b5b5d39b9b..7f964d159999 100644 --- a/packages/SystemUI/tests/src/com/android/systemui/wmshell/BubblesTest.java +++ b/packages/SystemUI/tests/src/com/android/systemui/wmshell/BubblesTest.java @@ -98,6 +98,8 @@ import android.view.WindowManager; import androidx.annotation.Nullable; import androidx.test.filters.SmallTest; +import com.android.app.viewcapture.ViewCapture; +import com.android.app.viewcapture.ViewCaptureAwareWindowManager; import com.android.internal.colorextraction.ColorExtractor; import com.android.internal.logging.UiEventLogger; import com.android.internal.statusbar.IStatusBarService; @@ -121,6 +123,8 @@ import com.android.systemui.shade.NotificationShadeWindowView; import com.android.systemui.shade.ShadeController; import com.android.systemui.shade.ShadeWindowLogger; import com.android.systemui.shade.domain.interactor.ShadeInteractor; +import com.android.systemui.shade.ui.viewmodel.NotificationShadeWindowModel; +import com.android.systemui.shared.notifications.domain.interactor.NotificationSettingsInteractor; import com.android.systemui.shared.system.QuickStepContract; import com.android.systemui.statusbar.NotificationEntryHelper; import com.android.systemui.statusbar.NotificationLockscreenUserManager; @@ -210,6 +214,7 @@ import java.util.List; import java.util.Optional; import java.util.concurrent.Executor; +import kotlin.Lazy; import platform.test.runner.parameterized.ParameterizedAndroidJunit4; import platform.test.runner.parameterized.Parameters; @@ -342,6 +347,9 @@ public class BubblesTest extends SysuiTestCase { private Icon mAppBubbleIcon; @Mock private Display mDefaultDisplay; + @Mock + private Lazy<ViewCapture> mLazyViewCapture; + @Mock private NotificationShadeWindowModel mNotificationShadeWindowModel; private final KosmosJavaAdapter mKosmos = new KosmosJavaAdapter(this); private ShadeInteractor mShadeInteractor; @@ -407,7 +415,8 @@ public class BubblesTest extends SysuiTestCase { mNotificationShadeWindowController = new NotificationShadeWindowControllerImpl( mContext, new FakeWindowRootViewComponent.Factory(mNotificationShadeWindowView), - mWindowManager, + new ViewCaptureAwareWindowManager(mWindowManager, mLazyViewCapture, + /* isViewCaptureEnabled= */ false), mActivityManager, mDozeParameters, mStatusBarStateController, @@ -424,6 +433,7 @@ public class BubblesTest extends SysuiTestCase { mShadeWindowLogger, () -> mSelectedUserInteractor, mUserTracker, + mNotificationShadeWindowModel, mKosmos::getCommunalInteractor ); mNotificationShadeWindowController.fetchWindowRootView(); @@ -480,7 +490,8 @@ public class BubblesTest extends SysuiTestCase { mock(PackageManager.class), Optional.of(mock(Bubbles.class)), mContext, - mock(NotificationManager.class) + mock(NotificationManager.class), + mock(NotificationSettingsInteractor.class) ); interruptionDecisionProvider.start(); diff --git a/packages/SystemUI/tests/utils/src/android/hardware/input/FakeInputManager.kt b/packages/SystemUI/tests/utils/src/android/hardware/input/FakeInputManager.kt index 6e7c05ca3f8f..ee36cadd8480 100644 --- a/packages/SystemUI/tests/utils/src/android/hardware/input/FakeInputManager.kt +++ b/packages/SystemUI/tests/utils/src/android/hardware/input/FakeInputManager.kt @@ -16,6 +16,7 @@ package android.hardware.input +import android.hardware.input.InputManager.InputDeviceListener import android.view.InputDevice import android.view.KeyCharacterMap import android.view.KeyCharacterMap.VIRTUAL_KEYBOARD @@ -47,6 +48,8 @@ class FakeInputManager { VIRTUAL_KEYBOARD to allKeyCodes.toMutableSet() ) + private var inputDeviceListener: InputDeviceListener? = null + val inputManager = mock<InputManager> { whenever(getInputDevice(anyInt())).thenAnswer { invocation -> @@ -84,6 +87,11 @@ class FakeInputManager { addPhysicalKeyboard(deviceId, enabled) } + fun registerInputDeviceListener(listener: InputDeviceListener) { + // TODO (b/355422259): handle this by listening to inputManager.registerInputDeviceListener + inputDeviceListener = listener + } + fun addPhysicalKeyboard(id: Int, enabled: Boolean = true) { check(id > 0) { "Physical keyboard ids have to be > 0" } addKeyboard(id, enabled) @@ -106,6 +114,16 @@ class FakeInputManager { supportedKeyCodesByDeviceId[id] = allKeyCodes.toMutableSet() } + fun addDevice(id: Int, sources: Int) { + devices[id] = InputDevice.Builder().setId(id).setSources(sources).build() + inputDeviceListener?.onInputDeviceAdded(id) + } + + fun removeDevice(id: Int) { + devices.remove(id) + inputDeviceListener?.onInputDeviceRemoved(id) + } + private fun InputDevice.copy( id: Int = getId(), type: Int = keyboardType, diff --git a/packages/SystemUI/tests/utils/src/com/android/systemui/TestMocksModule.kt b/packages/SystemUI/tests/utils/src/com/android/systemui/TestMocksModule.kt index 0b6b816e589f..50631409308c 100644 --- a/packages/SystemUI/tests/utils/src/com/android/systemui/TestMocksModule.kt +++ b/packages/SystemUI/tests/utils/src/com/android/systemui/TestMocksModule.kt @@ -33,6 +33,7 @@ import com.android.keyguard.KeyguardViewController import com.android.systemui.animation.DialogTransitionAnimator import com.android.systemui.biometrics.AuthController import com.android.systemui.bouncer.domain.interactor.PrimaryBouncerInteractor +import com.android.systemui.camera.CameraGestureHelper import com.android.systemui.communal.domain.interactor.CommunalInteractor import com.android.systemui.communal.domain.interactor.CommunalSceneInteractor import com.android.systemui.communal.domain.interactor.CommunalSettingsInteractor @@ -143,6 +144,7 @@ data class TestMocksModule( @get:Provides val primaryBouncerInteractor: PrimaryBouncerInteractor = mock(), @get:Provides val keyguardStateController: KeyguardStateController = mock(), @get:Provides val globalSettings: GlobalSettings = mock(), + @get:Provides val cameraGestureHelper: CameraGestureHelper = mock(), // log buffers @get:[Provides BroadcastDispatcherLog] diff --git a/packages/SystemUI/tests/utils/src/com/android/systemui/camera/CameraGestureHelperKosmos.kt b/packages/SystemUI/tests/utils/src/com/android/systemui/camera/CameraGestureHelperKosmos.kt new file mode 100644 index 000000000000..931567e4be78 --- /dev/null +++ b/packages/SystemUI/tests/utils/src/com/android/systemui/camera/CameraGestureHelperKosmos.kt @@ -0,0 +1,29 @@ +/* + * Copyright (C) 2024 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.android.systemui.camera + +import com.android.systemui.kosmos.Kosmos +import com.android.systemui.util.mockito.any +import com.android.systemui.util.mockito.whenever +import org.mockito.Mockito.mock + +val Kosmos.cameraGestureHelper: CameraGestureHelper by + Kosmos.Fixture<CameraGestureHelper> { + mock(CameraGestureHelper::class.java).also { helper -> + whenever(helper.canCameraGestureBeLaunched(any())).thenReturn(true) + } + } diff --git a/packages/SystemUI/tests/utils/src/com/android/systemui/haptics/qs/QSLongPressEffectKosmos.kt b/packages/SystemUI/tests/utils/src/com/android/systemui/haptics/qs/QSLongPressEffectKosmos.kt index 28355e1c3efa..ca748b661d04 100644 --- a/packages/SystemUI/tests/utils/src/com/android/systemui/haptics/qs/QSLongPressEffectKosmos.kt +++ b/packages/SystemUI/tests/utils/src/com/android/systemui/haptics/qs/QSLongPressEffectKosmos.kt @@ -16,10 +16,16 @@ package com.android.systemui.haptics.qs -import com.android.systemui.classifier.falsingManager import com.android.systemui.haptics.vibratorHelper import com.android.systemui.kosmos.Kosmos +import com.android.systemui.log.core.FakeLogBuffer import com.android.systemui.statusbar.policy.keyguardStateController val Kosmos.qsLongPressEffect by - Kosmos.Fixture { QSLongPressEffect(vibratorHelper, keyguardStateController, falsingManager) } + Kosmos.Fixture { + QSLongPressEffect( + vibratorHelper, + keyguardStateController, + FakeLogBuffer.Factory.create(), + ) + } 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 87143efb7f3c..727de9e95872 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 @@ -22,6 +22,7 @@ import com.android.systemui.dagger.SysUISingleton import com.android.systemui.keyguard.shared.model.BiometricUnlockMode import com.android.systemui.keyguard.shared.model.BiometricUnlockModel import com.android.systemui.keyguard.shared.model.BiometricUnlockSource +import com.android.systemui.keyguard.shared.model.CameraLaunchSourceModel import com.android.systemui.keyguard.shared.model.DismissAction import com.android.systemui.keyguard.shared.model.DozeTransitionModel import com.android.systemui.keyguard.shared.model.KeyguardDone @@ -138,6 +139,8 @@ class FakeKeyguardRepository @Inject constructor() : KeyguardRepository { private val _canIgnoreAuthAndReturnToGone = MutableStateFlow(false) override val canIgnoreAuthAndReturnToGone = _canIgnoreAuthAndReturnToGone.asStateFlow() + override val onCameraLaunchDetected = MutableStateFlow(CameraLaunchSourceModel()) + override fun setQuickSettingsVisible(isVisible: Boolean) { _isQuickSettingsVisible.value = isVisible } diff --git a/packages/SystemUI/tests/utils/src/com/android/systemui/keyguard/domain/interactor/KeyguardInteractorFactory.kt b/packages/SystemUI/tests/utils/src/com/android/systemui/keyguard/domain/interactor/KeyguardInteractorFactory.kt index b5ca964d6968..a95609efc16f 100644 --- a/packages/SystemUI/tests/utils/src/com/android/systemui/keyguard/domain/interactor/KeyguardInteractorFactory.kt +++ b/packages/SystemUI/tests/utils/src/com/android/systemui/keyguard/domain/interactor/KeyguardInteractorFactory.kt @@ -21,7 +21,6 @@ import com.android.systemui.bouncer.data.repository.FakeKeyguardBouncerRepositor import com.android.systemui.common.ui.data.repository.FakeConfigurationRepository import com.android.systemui.common.ui.domain.interactor.ConfigurationInteractor import com.android.systemui.flags.FakeFeatureFlags -import com.android.systemui.keyguard.data.repository.FakeCommandQueue import com.android.systemui.keyguard.data.repository.FakeKeyguardRepository import com.android.systemui.keyguard.shared.model.KeyguardState import com.android.systemui.keyguard.shared.model.TransitionStep @@ -49,7 +48,6 @@ object KeyguardInteractorFactory { fun create( featureFlags: FakeFeatureFlags = FakeFeatureFlags(), repository: FakeKeyguardRepository = FakeKeyguardRepository(), - commandQueue: FakeCommandQueue = FakeCommandQueue(), bouncerRepository: FakeKeyguardBouncerRepository = FakeKeyguardBouncerRepository(), configurationRepository: FakeConfigurationRepository = FakeConfigurationRepository(), shadeRepository: FakeShadeRepository = FakeShadeRepository(), @@ -87,7 +85,6 @@ object KeyguardInteractorFactory { } return WithDependencies( repository = repository, - commandQueue = commandQueue, featureFlags = featureFlags, bouncerRepository = bouncerRepository, configurationRepository = configurationRepository, @@ -95,7 +92,6 @@ object KeyguardInteractorFactory { powerInteractor = powerInteractor, KeyguardInteractor( repository = repository, - commandQueue = commandQueue, powerInteractor = powerInteractor, bouncerRepository = bouncerRepository, configurationInteractor = ConfigurationInteractor(configurationRepository), @@ -112,7 +108,6 @@ object KeyguardInteractorFactory { data class WithDependencies( val repository: FakeKeyguardRepository, - val commandQueue: FakeCommandQueue, val featureFlags: FakeFeatureFlags, val bouncerRepository: FakeKeyguardBouncerRepository, val configurationRepository: FakeConfigurationRepository, diff --git a/packages/SystemUI/tests/utils/src/com/android/systemui/keyguard/domain/interactor/KeyguardInteractorKosmos.kt b/packages/SystemUI/tests/utils/src/com/android/systemui/keyguard/domain/interactor/KeyguardInteractorKosmos.kt index 81d8f0b4ca53..5ab56e931175 100644 --- a/packages/SystemUI/tests/utils/src/com/android/systemui/keyguard/domain/interactor/KeyguardInteractorKosmos.kt +++ b/packages/SystemUI/tests/utils/src/com/android/systemui/keyguard/domain/interactor/KeyguardInteractorKosmos.kt @@ -18,7 +18,6 @@ package com.android.systemui.keyguard.domain.interactor import com.android.systemui.bouncer.data.repository.keyguardBouncerRepository import com.android.systemui.common.ui.domain.interactor.configurationInteractor -import com.android.systemui.keyguard.data.repository.fakeCommandQueue import com.android.systemui.keyguard.data.repository.keyguardRepository import com.android.systemui.kosmos.Kosmos import com.android.systemui.kosmos.testScope @@ -31,7 +30,6 @@ val Kosmos.keyguardInteractor: KeyguardInteractor by Kosmos.Fixture { KeyguardInteractor( repository = keyguardRepository, - commandQueue = fakeCommandQueue, powerInteractor = powerInteractor, bouncerRepository = keyguardBouncerRepository, configurationInteractor = configurationInteractor, diff --git a/packages/SystemUI/tests/utils/src/com/android/systemui/keyguard/gesture/data/GestureRepositoryKosmos.kt b/packages/SystemUI/tests/utils/src/com/android/systemui/keyguard/gesture/data/GestureRepositoryKosmos.kt new file mode 100644 index 000000000000..9bd346effdc3 --- /dev/null +++ b/packages/SystemUI/tests/utils/src/com/android/systemui/keyguard/gesture/data/GestureRepositoryKosmos.kt @@ -0,0 +1,25 @@ +/* + * Copyright (C) 2024 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.android.systemui.keyguard.gesture.data + +import com.android.systemui.kosmos.Kosmos +import com.android.systemui.kosmos.testDispatcher +import com.android.systemui.navigationbar.gestural.data.respository.GestureRepository +import com.android.systemui.navigationbar.gestural.data.respository.GestureRepositoryImpl + +val Kosmos.gestureRepository: GestureRepository by + Kosmos.Fixture { GestureRepositoryImpl(testDispatcher) } diff --git a/packages/SystemUI/tests/utils/src/com/android/systemui/keyguard/gesture/domain/GestureInteractorKosmos.kt b/packages/SystemUI/tests/utils/src/com/android/systemui/keyguard/gesture/domain/GestureInteractorKosmos.kt new file mode 100644 index 000000000000..658aaa6c1a62 --- /dev/null +++ b/packages/SystemUI/tests/utils/src/com/android/systemui/keyguard/gesture/domain/GestureInteractorKosmos.kt @@ -0,0 +1,27 @@ +/* + * Copyright (C) 2024 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.android.systemui.keyguard.gesture.domain + +import com.android.systemui.keyguard.gesture.data.gestureRepository +import com.android.systemui.kosmos.Kosmos +import com.android.systemui.kosmos.applicationCoroutineScope +import com.android.systemui.navigationbar.gestural.domain.GestureInteractor + +val Kosmos.gestureInteractor: GestureInteractor by + Kosmos.Fixture { + GestureInteractor(gestureRepository = gestureRepository, scope = applicationCoroutineScope) + } diff --git a/packages/SystemUI/tests/utils/src/com/android/systemui/keyguard/ui/binder/AlternateBouncerViewBinderKosmos.kt b/packages/SystemUI/tests/utils/src/com/android/systemui/keyguard/ui/binder/AlternateBouncerViewBinderKosmos.kt index 6eb8a4925082..2919d3f575c6 100644 --- a/packages/SystemUI/tests/utils/src/com/android/systemui/keyguard/ui/binder/AlternateBouncerViewBinderKosmos.kt +++ b/packages/SystemUI/tests/utils/src/com/android/systemui/keyguard/ui/binder/AlternateBouncerViewBinderKosmos.kt @@ -25,6 +25,7 @@ import com.android.systemui.biometrics.domain.interactor.udfpsOverlayInteractor import com.android.systemui.common.ui.domain.interactor.configurationInteractor import com.android.systemui.deviceentry.domain.interactor.deviceEntryUdfpsInteractor import com.android.systemui.deviceentry.ui.viewmodel.AlternateBouncerUdfpsAccessibilityOverlayViewModel +import com.android.systemui.keyguard.dismissCallbackRegistry import com.android.systemui.keyguard.ui.SwipeUpAnywhereGestureHandler import com.android.systemui.keyguard.ui.viewmodel.AlternateBouncerDependencies import com.android.systemui.keyguard.ui.viewmodel.AlternateBouncerMessageAreaViewModel @@ -49,6 +50,7 @@ val Kosmos.alternateBouncerViewBinder by alternateBouncerDependencies = { alternateBouncerDependencies }, windowManager = { windowManager }, layoutInflater = { mockedLayoutInflater }, + dismissCallbackRegistry = dismissCallbackRegistry, ) } diff --git a/packages/SystemUI/tests/utils/src/com/android/systemui/keyguard/ui/viewmodel/AlternateBouncerToLockscreenTransitionViewModelKosmos.kt b/packages/SystemUI/tests/utils/src/com/android/systemui/keyguard/ui/viewmodel/AlternateBouncerToLockscreenTransitionViewModelKosmos.kt new file mode 100644 index 000000000000..6c644eee24ff --- /dev/null +++ b/packages/SystemUI/tests/utils/src/com/android/systemui/keyguard/ui/viewmodel/AlternateBouncerToLockscreenTransitionViewModelKosmos.kt @@ -0,0 +1,30 @@ +/* + * Copyright (C) 2024 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +@file:OptIn(ExperimentalCoroutinesApi::class) + +package com.android.systemui.keyguard.ui.viewmodel + +import com.android.systemui.keyguard.ui.keyguardTransitionAnimationFlow +import com.android.systemui.kosmos.Kosmos +import com.android.systemui.kosmos.Kosmos.Fixture +import kotlinx.coroutines.ExperimentalCoroutinesApi + +val Kosmos.alternateBouncerToLockscreenTransitionViewModel by Fixture { + AlternateBouncerToLockscreenTransitionViewModel( + animationFlow = keyguardTransitionAnimationFlow, + ) +} diff --git a/packages/SystemUI/tests/utils/src/com/android/systemui/keyguard/ui/viewmodel/KeyguardRootViewModelKosmos.kt b/packages/SystemUI/tests/utils/src/com/android/systemui/keyguard/ui/viewmodel/KeyguardRootViewModelKosmos.kt index 3c5baa557513..82860fc52045 100644 --- a/packages/SystemUI/tests/utils/src/com/android/systemui/keyguard/ui/viewmodel/KeyguardRootViewModelKosmos.kt +++ b/packages/SystemUI/tests/utils/src/com/android/systemui/keyguard/ui/viewmodel/KeyguardRootViewModelKosmos.kt @@ -40,6 +40,8 @@ val Kosmos.keyguardRootViewModel by Fixture { keyguardTransitionInteractor = keyguardTransitionInteractor, notificationsKeyguardInteractor = notificationsKeyguardInteractor, alternateBouncerToGoneTransitionViewModel = alternateBouncerToGoneTransitionViewModel, + alternateBouncerToLockscreenTransitionViewModel = + alternateBouncerToLockscreenTransitionViewModel, aodToGoneTransitionViewModel = aodToGoneTransitionViewModel, aodToLockscreenTransitionViewModel = aodToLockscreenTransitionViewModel, aodToOccludedTransitionViewModel = aodToOccludedTransitionViewModel, diff --git a/packages/SystemUI/tests/utils/src/com/android/systemui/power/domain/interactor/PowerInteractorFactory.kt b/packages/SystemUI/tests/utils/src/com/android/systemui/power/domain/interactor/PowerInteractorFactory.kt index d92ace945b18..9a07c4e94276 100644 --- a/packages/SystemUI/tests/utils/src/com/android/systemui/power/domain/interactor/PowerInteractorFactory.kt +++ b/packages/SystemUI/tests/utils/src/com/android/systemui/power/domain/interactor/PowerInteractorFactory.kt @@ -42,6 +42,7 @@ object PowerInteractorFactory { falsingCollector, screenOffAnimationController, statusBarStateController, + mock(), ) ) } diff --git a/packages/SystemUI/tests/utils/src/com/android/systemui/power/domain/interactor/PowerInteractorKosmos.kt b/packages/SystemUI/tests/utils/src/com/android/systemui/power/domain/interactor/PowerInteractorKosmos.kt index 8486691a7b95..d50091e1447c 100644 --- a/packages/SystemUI/tests/utils/src/com/android/systemui/power/domain/interactor/PowerInteractorKosmos.kt +++ b/packages/SystemUI/tests/utils/src/com/android/systemui/power/domain/interactor/PowerInteractorKosmos.kt @@ -16,6 +16,7 @@ package com.android.systemui.power.domain.interactor +import com.android.systemui.camera.cameraGestureHelper import com.android.systemui.classifier.falsingCollector import com.android.systemui.kosmos.Kosmos import com.android.systemui.plugins.statusbar.statusBarStateController @@ -29,5 +30,6 @@ val Kosmos.powerInteractor by falsingCollector = falsingCollector, screenOffAnimationController = screenOffAnimationController, statusBarStateController = statusBarStateController, + cameraGestureHelper = { cameraGestureHelper }, ) } diff --git a/packages/SystemUI/tests/utils/src/com/android/systemui/settings/FakeUserTracker.kt b/packages/SystemUI/tests/utils/src/com/android/systemui/settings/FakeUserTracker.kt index 2ca338a3af9c..f3d5b7d77669 100644 --- a/packages/SystemUI/tests/utils/src/com/android/systemui/settings/FakeUserTracker.kt +++ b/packages/SystemUI/tests/utils/src/com/android/systemui/settings/FakeUserTracker.kt @@ -33,7 +33,7 @@ class FakeUserTracker( private var _userHandle: UserHandle = UserHandle.of(_userId), private var _userInfo: UserInfo = mock(), private var _userProfiles: List<UserInfo> = emptyList(), - userContentResolver: ContentResolver = MockContentResolver(), + userContentResolverProvider: () -> ContentResolver = { MockContentResolver() }, userContext: Context = mock(), private val onCreateCurrentUserContext: (Context) -> Context = { mock() }, ) : UserTracker { @@ -41,14 +41,19 @@ class FakeUserTracker( override val userId: Int get() = _userId + override val userHandle: UserHandle get() = _userHandle + override val userInfo: UserInfo get() = _userInfo + override val userProfiles: List<UserInfo> get() = _userProfiles - override val userContentResolver: ContentResolver = userContentResolver + // userContentResolver is lazy because Ravenwood doesn't support MockContentResolver() + // and we still want to allow people use this class for tests that don't use it. + override val userContentResolver: ContentResolver by lazy { userContentResolverProvider() } override val userContext: Context = userContext override fun addCallback(callback: UserTracker.Callback, executor: Executor) { diff --git a/packages/SystemUI/tests/utils/src/com/android/systemui/shade/domain/startable/ShadeStartableKosmos.kt b/packages/SystemUI/tests/utils/src/com/android/systemui/shade/domain/startable/ShadeStartableKosmos.kt index 79b80bc71c58..a1f157f13210 100644 --- a/packages/SystemUI/tests/utils/src/com/android/systemui/shade/domain/startable/ShadeStartableKosmos.kt +++ b/packages/SystemUI/tests/utils/src/com/android/systemui/shade/domain/startable/ShadeStartableKosmos.kt @@ -17,6 +17,7 @@ package com.android.systemui.shade.domain.startable import android.content.applicationContext +import com.android.systemui.biometrics.domain.interactor.displayStateInteractor import com.android.systemui.common.ui.data.repository.configurationRepository import com.android.systemui.kosmos.Kosmos import com.android.systemui.kosmos.Kosmos.Fixture @@ -28,6 +29,7 @@ import com.android.systemui.shade.data.repository.shadeRepository import com.android.systemui.shade.domain.interactor.panelExpansionInteractor import com.android.systemui.shade.transition.ScrimShadeTransitionController import com.android.systemui.statusbar.notification.stack.notificationStackScrollLayoutController +import com.android.systemui.statusbar.phone.scrimController import com.android.systemui.statusbar.policy.splitShadeStateController import com.android.systemui.statusbar.pulseExpansionHandler import com.android.systemui.util.mockito.mock @@ -48,6 +50,8 @@ val Kosmos.shadeStartable by Fixture { panelExpansionInteractorProvider = { panelExpansionInteractor }, shadeExpansionStateManager = shadeExpansionStateManager, pulseExpansionHandler = pulseExpansionHandler, + displayStateInteractor = displayStateInteractor, nsslc = notificationStackScrollLayoutController, + scrimController = scrimController, ) } diff --git a/packages/SystemUI/tests/utils/src/com/android/systemui/shade/ui/viewmodel/NotificationsShadeWindowModelKosmos.kt b/packages/SystemUI/tests/utils/src/com/android/systemui/shade/ui/viewmodel/NotificationsShadeWindowModelKosmos.kt new file mode 100644 index 000000000000..cd4fab8d2970 --- /dev/null +++ b/packages/SystemUI/tests/utils/src/com/android/systemui/shade/ui/viewmodel/NotificationsShadeWindowModelKosmos.kt @@ -0,0 +1,23 @@ +/* + * Copyright (C) 2024 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.android.systemui.shade.ui.viewmodel + +import com.android.systemui.keyguard.domain.interactor.keyguardTransitionInteractor +import com.android.systemui.kosmos.Kosmos + +val Kosmos.notificationShadeWindowModel: NotificationShadeWindowModel by + Kosmos.Fixture { NotificationShadeWindowModel(keyguardTransitionInteractor) } diff --git a/packages/SystemUI/tests/utils/src/com/android/systemui/shared/notifications/data/repository/NotificationSettingsRepositoryKosmos.kt b/packages/SystemUI/tests/utils/src/com/android/systemui/shared/notifications/data/repository/NotificationSettingsRepositoryKosmos.kt index a75d2bc4aaf6..637385152a0a 100644 --- a/packages/SystemUI/tests/utils/src/com/android/systemui/shared/notifications/data/repository/NotificationSettingsRepositoryKosmos.kt +++ b/packages/SystemUI/tests/utils/src/com/android/systemui/shared/notifications/data/repository/NotificationSettingsRepositoryKosmos.kt @@ -20,12 +20,14 @@ import com.android.systemui.kosmos.Kosmos import com.android.systemui.kosmos.testDispatcher import com.android.systemui.kosmos.testScope import com.android.systemui.shared.settings.data.repository.secureSettingsRepository +import com.android.systemui.shared.settings.data.repository.systemSettingsRepository val Kosmos.notificationSettingsRepository by Kosmos.Fixture { NotificationSettingsRepository( - scope = testScope.backgroundScope, + backgroundScope = testScope.backgroundScope, backgroundDispatcher = testDispatcher, secureSettingsRepository = secureSettingsRepository, + systemSettingsRepository = systemSettingsRepository, ) } diff --git a/packages/SystemUI/tests/utils/src/com/android/systemui/shared/settings/data/repository/SystemSettingsRepositoryKosmos.kt b/packages/SystemUI/tests/utils/src/com/android/systemui/shared/settings/data/repository/SystemSettingsRepositoryKosmos.kt new file mode 100644 index 000000000000..01f19ae725e7 --- /dev/null +++ b/packages/SystemUI/tests/utils/src/com/android/systemui/shared/settings/data/repository/SystemSettingsRepositoryKosmos.kt @@ -0,0 +1,23 @@ +/* + * Copyright (C) 2024 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.android.systemui.shared.settings.data.repository + +import com.android.systemui.kosmos.Kosmos + +var Kosmos.systemSettingsRepository: SystemSettingsRepository by + Kosmos.Fixture { fakeSystemSettingsRepository } +val Kosmos.fakeSystemSettingsRepository by Kosmos.Fixture { FakeSystemSettingsRepository() } diff --git a/packages/SystemUI/tests/utils/src/com/android/systemui/statusbar/policy/domain/interactor/ZenModeInteractorKosmos.kt b/packages/SystemUI/tests/utils/src/com/android/systemui/statusbar/policy/domain/interactor/ZenModeInteractorKosmos.kt index 78242b69854b..aef08286262b 100644 --- a/packages/SystemUI/tests/utils/src/com/android/systemui/statusbar/policy/domain/interactor/ZenModeInteractorKosmos.kt +++ b/packages/SystemUI/tests/utils/src/com/android/systemui/statusbar/policy/domain/interactor/ZenModeInteractorKosmos.kt @@ -18,10 +18,12 @@ package com.android.systemui.statusbar.policy.domain.interactor import com.android.systemui.kosmos.Kosmos import com.android.systemui.kosmos.Kosmos.Fixture +import com.android.systemui.shared.notifications.data.repository.notificationSettingsRepository import com.android.systemui.statusbar.policy.data.repository.zenModeRepository val Kosmos.zenModeInteractor by Fixture { ZenModeInteractor( - repository = zenModeRepository, + zenModeRepository = zenModeRepository, + notificationSettingsRepository = notificationSettingsRepository, ) } diff --git a/packages/SystemUI/tests/utils/src/com/android/systemui/util/settings/FakeGlobalSettings.java b/packages/SystemUI/tests/utils/src/com/android/systemui/util/settings/FakeGlobalSettings.java index 476b7d8376c8..65f4122f773e 100644 --- a/packages/SystemUI/tests/utils/src/com/android/systemui/util/settings/FakeGlobalSettings.java +++ b/packages/SystemUI/tests/utils/src/com/android/systemui/util/settings/FakeGlobalSettings.java @@ -38,6 +38,11 @@ public class FakeGlobalSettings implements GlobalSettings { public static final Uri CONTENT_URI = Uri.parse("content://settings/fake_global"); + /** + * @deprecated Please use FakeGlobalSettings(testDispatcher) to provide the same dispatcher used + * by main test scope. + */ + @Deprecated public FakeGlobalSettings() { mDispatcher = StandardTestDispatcher(/* scheduler = */ null, /* name = */ null); } @@ -46,6 +51,7 @@ public class FakeGlobalSettings implements GlobalSettings { mDispatcher = dispatcher; } + @NonNull @Override public ContentResolver getContentResolver() { throw new UnsupportedOperationException( @@ -53,6 +59,7 @@ public class FakeGlobalSettings implements GlobalSettings { + "GlobalSettings.registerContentObserver helpful instead."); } + @NonNull @Override public CoroutineDispatcher getBackgroundDispatcher() { return mDispatcher; @@ -60,7 +67,7 @@ public class FakeGlobalSettings implements GlobalSettings { @Override public void registerContentObserverSync(Uri uri, boolean notifyDescendants, - ContentObserver settingsObserver) { + @NonNull ContentObserver settingsObserver) { List<ContentObserver> observers; mContentObserversAllUsers.putIfAbsent(uri.toString(), new ArrayList<>()); observers = mContentObserversAllUsers.get(uri.toString()); @@ -68,25 +75,26 @@ public class FakeGlobalSettings implements GlobalSettings { } @Override - public void unregisterContentObserverSync(ContentObserver settingsObserver) { + public void unregisterContentObserverSync(@NonNull ContentObserver settingsObserver) { for (Map.Entry<String, List<ContentObserver>> entry : mContentObserversAllUsers.entrySet()) { entry.getValue().remove(settingsObserver); } } + @NonNull @Override - public Uri getUriFor(String name) { + public Uri getUriFor(@NonNull String name) { return Uri.withAppendedPath(CONTENT_URI, name); } @Override - public String getString(String name) { + public String getString(@NonNull String name) { return mValues.get(getUriFor(name).toString()); } @Override - public boolean putString(String name, String value) { + public boolean putString(@NonNull String name, @NonNull String value) { return putString(name, value, null, false); } diff --git a/packages/SystemUI/tests/utils/src/com/android/systemui/util/settings/FakeGlobalSettingsKosmos.kt b/packages/SystemUI/tests/utils/src/com/android/systemui/util/settings/FakeGlobalSettingsKosmos.kt index df6fc41e5f3e..35fa2af7639f 100644 --- a/packages/SystemUI/tests/utils/src/com/android/systemui/util/settings/FakeGlobalSettingsKosmos.kt +++ b/packages/SystemUI/tests/utils/src/com/android/systemui/util/settings/FakeGlobalSettingsKosmos.kt @@ -18,5 +18,6 @@ package com.android.systemui.util.settings import com.android.systemui.kosmos.Kosmos import com.android.systemui.kosmos.Kosmos.Fixture +import com.android.systemui.kosmos.testDispatcher -val Kosmos.fakeGlobalSettings: FakeGlobalSettings by Fixture { FakeGlobalSettings() } +val Kosmos.fakeGlobalSettings: FakeGlobalSettings by Fixture { FakeGlobalSettings(testDispatcher) } diff --git a/packages/SystemUI/tests/utils/src/com/android/systemui/util/settings/FakeSettings.java b/packages/SystemUI/tests/utils/src/com/android/systemui/util/settings/FakeSettings.java index e35da11ff034..3f0318b71f8b 100644 --- a/packages/SystemUI/tests/utils/src/com/android/systemui/util/settings/FakeSettings.java +++ b/packages/SystemUI/tests/utils/src/com/android/systemui/util/settings/FakeSettings.java @@ -26,7 +26,9 @@ import android.os.UserHandle; import android.util.Pair; import androidx.annotation.NonNull; +import androidx.annotation.VisibleForTesting; +import com.android.systemui.settings.FakeUserTracker; import com.android.systemui.settings.UserTracker; import kotlinx.coroutines.CoroutineDispatcher; @@ -42,49 +44,68 @@ public class FakeSettings implements SecureSettings, SystemSettings { new HashMap<>(); private final Map<String, List<ContentObserver>> mContentObserversAllUsers = new HashMap<>(); private final CoroutineDispatcher mDispatcher; + private final UserTracker mUserTracker; public static final Uri CONTENT_URI = Uri.parse("content://settings/fake"); @UserIdInt private int mUserId = UserHandle.USER_CURRENT; + /** + * @deprecated Please use FakeSettings(testDispatcher) to provide the same dispatcher used + * by main test scope. + */ + @Deprecated public FakeSettings() { mDispatcher = StandardTestDispatcher(/* scheduler = */ null, /* name = */ null); + mUserTracker = new FakeUserTracker(); } public FakeSettings(CoroutineDispatcher dispatcher) { mDispatcher = dispatcher; + mUserTracker = new FakeUserTracker(); } - public FakeSettings(String initialKey, String initialValue) { - mDispatcher = StandardTestDispatcher(/* scheduler = */ null, /* name = */ null); + public FakeSettings(CoroutineDispatcher dispatcher, UserTracker userTracker) { + mDispatcher = dispatcher; + mUserTracker = userTracker; + } + + @VisibleForTesting + FakeSettings(String initialKey, String initialValue) { + this(); putString(initialKey, initialValue); } - public FakeSettings(Map<String, String> initialValues) { - mDispatcher = StandardTestDispatcher(/* scheduler = */ null, /* name = */ null); + @VisibleForTesting + FakeSettings(Map<String, String> initialValues) { + this(); for (Map.Entry<String, String> kv : initialValues.entrySet()) { putString(kv.getKey(), kv.getValue()); } } @Override + @NonNull public ContentResolver getContentResolver() { - return null; + throw new UnsupportedOperationException( + "FakeSettings.getContentResolver is not implemented"); } + @NonNull @Override public UserTracker getUserTracker() { - return null; + return mUserTracker; } + @NonNull @Override public CoroutineDispatcher getBackgroundDispatcher() { return mDispatcher; } @Override - public void registerContentObserverForUserSync(Uri uri, boolean notifyDescendants, - ContentObserver settingsObserver, int userHandle) { + public void registerContentObserverForUserSync(@NonNull Uri uri, boolean notifyDescendants, + @NonNull ContentObserver settingsObserver, int userHandle) { List<ContentObserver> observers; if (userHandle == UserHandle.USER_ALL) { mContentObserversAllUsers.putIfAbsent(uri.toString(), new ArrayList<>()); @@ -98,19 +119,18 @@ public class FakeSettings implements SecureSettings, SystemSettings { } @Override - public void unregisterContentObserverSync(ContentObserver settingsObserver) { - for (SettingsKey key : mContentObservers.keySet()) { - List<ContentObserver> observers = mContentObservers.get(key); + public void unregisterContentObserverSync(@NonNull ContentObserver settingsObserver) { + for (List<ContentObserver> observers : mContentObservers.values()) { observers.remove(settingsObserver); } - for (String key : mContentObserversAllUsers.keySet()) { - List<ContentObserver> observers = mContentObserversAllUsers.get(key); + for (List<ContentObserver> observers : mContentObserversAllUsers.values()) { observers.remove(settingsObserver); } } + @NonNull @Override - public Uri getUriFor(String name) { + public Uri getUriFor(@NonNull String name) { return Uri.withAppendedPath(CONTENT_URI, name); } @@ -124,33 +144,34 @@ public class FakeSettings implements SecureSettings, SystemSettings { } @Override - public String getString(String name) { + public String getString(@NonNull String name) { return getStringForUser(name, getUserId()); } @Override - public String getStringForUser(String name, int userHandle) { + public String getStringForUser(@NonNull String name, int userHandle) { return mValues.get(new SettingsKey(userHandle, getUriFor(name).toString())); } @Override - public boolean putString(String name, String value, boolean overrideableByRestore) { + public boolean putString(@NonNull String name, @NonNull String value, + boolean overrideableByRestore) { return putStringForUser(name, value, null, false, getUserId(), overrideableByRestore); } @Override - public boolean putString(String name, String value) { + public boolean putString(@NonNull String name, @NonNull String value) { return putString(name, value, false); } @Override - public boolean putStringForUser(String name, String value, int userHandle) { + public boolean putStringForUser(@NonNull String name, @NonNull String value, int userHandle) { return putStringForUser(name, value, null, false, userHandle, false); } @Override - public boolean putStringForUser(String name, String value, String tag, boolean makeDefault, - int userHandle, boolean overrideableByRestore) { + public boolean putStringForUser(@NonNull String name, @NonNull String value, String tag, + boolean makeDefault, int userHandle, boolean overrideableByRestore) { SettingsKey key = new SettingsKey(userHandle, getUriFor(name).toString()); mValues.put(key, value); @@ -166,7 +187,8 @@ public class FakeSettings implements SecureSettings, SystemSettings { } @Override - public boolean putString(@NonNull String name, String value, String tag, boolean makeDefault) { + public boolean putString(@NonNull String name, @NonNull String value, @NonNull String tag, + boolean makeDefault) { return putString(name, value); } diff --git a/packages/SystemUI/tests/utils/src/com/android/systemui/util/settings/FakeSettingsKosmos.kt b/packages/SystemUI/tests/utils/src/com/android/systemui/util/settings/FakeSettingsKosmos.kt index bcb584858e32..55044bf3650b 100644 --- a/packages/SystemUI/tests/utils/src/com/android/systemui/util/settings/FakeSettingsKosmos.kt +++ b/packages/SystemUI/tests/utils/src/com/android/systemui/util/settings/FakeSettingsKosmos.kt @@ -18,5 +18,7 @@ package com.android.systemui.util.settings import com.android.systemui.kosmos.Kosmos import com.android.systemui.kosmos.Kosmos.Fixture +import com.android.systemui.kosmos.testDispatcher +import com.android.systemui.settings.fakeUserTracker -val Kosmos.fakeSettings: FakeSettings by Fixture { FakeSettings() } +val Kosmos.fakeSettings: FakeSettings by Fixture { FakeSettings(testDispatcher, fakeUserTracker) } diff --git a/packages/SystemUI/tests/utils/src/com/android/systemui/volume/data/repository/FakeAudioSharingRepository.kt b/packages/SystemUI/tests/utils/src/com/android/systemui/volume/data/repository/FakeAudioSharingRepository.kt index d391750a2612..0a617d17b033 100644 --- a/packages/SystemUI/tests/utils/src/com/android/systemui/volume/data/repository/FakeAudioSharingRepository.kt +++ b/packages/SystemUI/tests/utils/src/com/android/systemui/volume/data/repository/FakeAudioSharingRepository.kt @@ -16,10 +16,7 @@ package com.android.systemui.volume.data.repository -import androidx.annotation.IntRange import com.android.settingslib.volume.data.repository.AudioSharingRepository -import com.android.settingslib.volume.data.repository.AudioSharingRepository.Companion.AUDIO_SHARING_VOLUME_MAX -import com.android.settingslib.volume.data.repository.AudioSharingRepository.Companion.AUDIO_SHARING_VOLUME_MIN import com.android.settingslib.volume.data.repository.GroupIdToVolumes import kotlinx.coroutines.flow.Flow import kotlinx.coroutines.flow.MutableStateFlow @@ -27,11 +24,14 @@ import kotlinx.coroutines.flow.StateFlow class FakeAudioSharingRepository : AudioSharingRepository { private val mutableInAudioSharing: MutableStateFlow<Boolean> = MutableStateFlow(false) + private val mutablePrimaryGroupId: MutableStateFlow<Int> = + MutableStateFlow(TEST_GROUP_ID_INVALID) private val mutableSecondaryGroupId: MutableStateFlow<Int> = MutableStateFlow(TEST_GROUP_ID_INVALID) private val mutableVolumeMap: MutableStateFlow<GroupIdToVolumes> = MutableStateFlow(emptyMap()) override val inAudioSharing: Flow<Boolean> = mutableInAudioSharing + override val primaryGroupId: StateFlow<Int> = mutablePrimaryGroupId override val secondaryGroupId: StateFlow<Int> = mutableSecondaryGroupId override val volumeMap: StateFlow<GroupIdToVolumes> = mutableVolumeMap @@ -41,6 +41,10 @@ class FakeAudioSharingRepository : AudioSharingRepository { mutableInAudioSharing.value = state } + fun setPrimaryGroupId(groupId: Int) { + mutablePrimaryGroupId.value = groupId + } + fun setSecondaryGroupId(groupId: Int) { mutableSecondaryGroupId.value = groupId } diff --git a/packages/SystemUI/tests/utils/src/com/android/systemui/volume/domain/interactor/AudioSharingInteractorKosmos.kt b/packages/SystemUI/tests/utils/src/com/android/systemui/volume/domain/interactor/AudioSharingInteractorKosmos.kt index 03981bbef444..ce8aba540ec8 100644 --- a/packages/SystemUI/tests/utils/src/com/android/systemui/volume/domain/interactor/AudioSharingInteractorKosmos.kt +++ b/packages/SystemUI/tests/utils/src/com/android/systemui/volume/domain/interactor/AudioSharingInteractorKosmos.kt @@ -18,12 +18,15 @@ package com.android.systemui.volume.domain.interactor import com.android.systemui.kosmos.Kosmos import com.android.systemui.kosmos.applicationCoroutineScope +import com.android.systemui.kosmos.backgroundCoroutineContext import com.android.systemui.volume.data.repository.audioSharingRepository val Kosmos.audioSharingInteractor by Kosmos.Fixture { AudioSharingInteractorImpl( applicationCoroutineScope, + backgroundCoroutineContext, + audioVolumeInteractor, audioSharingRepository, ) } diff --git a/ravenwood/Android.bp b/ravenwood/Android.bp index 8d89cc1f4a9b..7c8fd42cd540 100644 --- a/ravenwood/Android.bp +++ b/ravenwood/Android.bp @@ -68,7 +68,10 @@ java_library { srcs: [ "runtime-common-ravenwood-src/**/*.java", ], - visibility: ["//frameworks/base"], + visibility: [ + // Some tests need to access the utilities. + ":__subpackages__", + ], } java_library { @@ -318,6 +321,9 @@ java_library { android_ravenwood_libgroup { name: "ravenwood-runtime", + data: [ + "framework-res", + ], libs: [ "100-framework-minus-apex.ravenwood", "200-kxml2-android", @@ -330,6 +336,11 @@ android_ravenwood_libgroup { "services.core.ravenwood-jarjar", "services.fakes.ravenwood-jarjar", + // ICU + "core-icu4j-for-host.ravenwood", + "icu4j-icudata-jarjar", + "icu4j-icutzdata-jarjar", + // Provide runtime versions of utils linked in below "junit", "truth", diff --git a/ravenwood/TEST_MAPPING b/ravenwood/TEST_MAPPING index f6885e1e74ba..fbf27fa5bf4b 100644 --- a/ravenwood/TEST_MAPPING +++ b/ravenwood/TEST_MAPPING @@ -12,6 +12,9 @@ { "name": "RavenwoodBivalentTest_device" }, + { + "name": "RavenwoodResApkTest" + }, // The sysui tests should match vendor/unbundled_google/packages/SystemUIGoogle/TEST_MAPPING { "name": "SystemUIGoogleTests", diff --git a/ravenwood/resapk_test/Android.bp b/ravenwood/resapk_test/Android.bp new file mode 100644 index 000000000000..c14576550f78 --- /dev/null +++ b/ravenwood/resapk_test/Android.bp @@ -0,0 +1,30 @@ +package { + // See: http://go/android-license-faq + // A large-scale-change added 'default_applicable_licenses' to import + // all of the 'license_kinds' from "frameworks_base_license" + // to get the below license kinds: + // SPDX-license-identifier-Apache-2.0 + default_applicable_licenses: ["frameworks_base_license"], +} + +android_ravenwood_test { + name: "RavenwoodResApkTest", + + resource_apk: "RavenwoodResApkTest-apk", + + libs: [ + // Normally, tests shouldn't directly access it, but we need to access RavenwoodCommonUtils + // in this test. + "ravenwood-runtime-common-ravenwood", + ], + static_libs: [ + "androidx.annotation_annotation", + "androidx.test.ext.junit", + "androidx.test.rules", + ], + srcs: [ + "test/**/*.java", + ], + sdk_version: "test_current", + auto_gen_config: true, +} diff --git a/ravenwood/resapk_test/apk/Android.bp b/ravenwood/resapk_test/apk/Android.bp new file mode 100644 index 000000000000..10ed5e2f8410 --- /dev/null +++ b/ravenwood/resapk_test/apk/Android.bp @@ -0,0 +1,14 @@ +package { + // See: http://go/android-license-faq + // A large-scale-change added 'default_applicable_licenses' to import + // all of the 'license_kinds' from "frameworks_base_license" + // to get the below license kinds: + // SPDX-license-identifier-Apache-2.0 + default_applicable_licenses: ["frameworks_base_license"], +} + +android_app { + name: "RavenwoodResApkTest-apk", + + sdk_version: "current", +} diff --git a/ravenwood/resapk_test/apk/AndroidManifest.xml b/ravenwood/resapk_test/apk/AndroidManifest.xml new file mode 100644 index 000000000000..f34d8b2f4e81 --- /dev/null +++ b/ravenwood/resapk_test/apk/AndroidManifest.xml @@ -0,0 +1,19 @@ +<?xml version="1.0" encoding="utf-8"?> +<!-- Copyright (C) 2024 The Android Open Source Project + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. +--> + +<manifest xmlns:android="http://schemas.android.com/apk/res/android" + package="com.android.ravenwood.restest_apk"> +</manifest> diff --git a/ravenwood/resapk_test/apk/res/values/strings.xml b/ravenwood/resapk_test/apk/res/values/strings.xml new file mode 100644 index 000000000000..23d4c0f21007 --- /dev/null +++ b/ravenwood/resapk_test/apk/res/values/strings.xml @@ -0,0 +1,19 @@ +<?xml version="1.0" encoding="utf-8"?> +<!-- Copyright (C) 2024 The Android Open Source Project + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. +--> +<resources xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> + <!-- Test string 1 --> + <string name="test_string_1" translatable="false" >Test String 1</string> +</resources> diff --git a/ravenwood/resapk_test/test/com/android/ravenwood/resapk_test/RavenwoodResApkTest.java b/ravenwood/resapk_test/test/com/android/ravenwood/resapk_test/RavenwoodResApkTest.java new file mode 100644 index 000000000000..1029ed2bee3b --- /dev/null +++ b/ravenwood/resapk_test/test/com/android/ravenwood/resapk_test/RavenwoodResApkTest.java @@ -0,0 +1,51 @@ +/* + * Copyright (C) 2024 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package com.android.ravenwood.resapk_test; + + +import static junit.framework.TestCase.assertTrue; + +import androidx.test.ext.junit.runners.AndroidJUnit4; + +import com.android.ravenwood.common.RavenwoodCommonUtils; + +import org.junit.Test; +import org.junit.runner.RunWith; + +import java.io.File; + +@RunWith(AndroidJUnit4.class) +public class RavenwoodResApkTest { + /** + * Ensure the file "ravenwood-res.apk" exists. + * TODO Check the content of it, once Ravenwood supports resources. The file should + * be a copy of RavenwoodResApkTest-apk.apk + */ + @Test + public void testResApkExists() { + var file = "ravenwood-res-apks/ravenwood-res.apk"; + + assertTrue(new File(file).exists()); + } + + @Test + public void testFrameworkResExists() { + var file = "ravenwood-data/framework-res.apk"; + + assertTrue(new File( + RavenwoodCommonUtils.getRavenwoodRuntimePath() + "/" + file).exists()); + } +} diff --git a/ravenwood/runtime-helper-src/framework/com/android/platform/test/ravenwood/nativesubstitution/ParcelFileDescriptor_host.java b/ravenwood/runtime-helper-src/framework/com/android/platform/test/ravenwood/nativesubstitution/ParcelFileDescriptor_host.java index 8fe6853abb45..1a15d7a8c19e 100644 --- a/ravenwood/runtime-helper-src/framework/com/android/platform/test/ravenwood/nativesubstitution/ParcelFileDescriptor_host.java +++ b/ravenwood/runtime-helper-src/framework/com/android/platform/test/ravenwood/nativesubstitution/ParcelFileDescriptor_host.java @@ -25,19 +25,24 @@ import static android.os.ParcelFileDescriptor.MODE_WORLD_READABLE; import static android.os.ParcelFileDescriptor.MODE_WORLD_WRITEABLE; import static android.os.ParcelFileDescriptor.MODE_WRITE_ONLY; +import android.system.ErrnoException; +import android.system.Os; +import android.util.Log; + import com.android.internal.annotations.GuardedBy; import com.android.ravenwood.common.JvmWorkaround; import java.io.File; import java.io.FileDescriptor; import java.io.FileNotFoundException; -import java.io.FileOutputStream; import java.io.IOException; import java.io.RandomAccessFile; import java.util.HashMap; import java.util.Map; public class ParcelFileDescriptor_host { + private static final String TAG = "ParcelFileDescriptor_host"; + /** * Since we don't have a great way to keep an unmanaged {@code FileDescriptor} reference * alive, we keep a strong reference to the {@code RandomAccessFile} we used to open it. This @@ -98,16 +103,18 @@ public class ParcelFileDescriptor_host { synchronized (sActive) { raf = sActive.remove(fd); } + int fdInt = JvmWorkaround.getInstance().getFdInt(fd); try { if (raf != null) { raf.close(); } else { - // Odd, we don't remember opening this ourselves, but let's release the - // underlying resource as requested - System.err.println("Closing unknown FileDescriptor: " + fd); - new FileOutputStream(fd).close(); + // This FD wasn't created by native_open$ravenwood(). + // The FD was passed to the PFD ctor. Just close it. + Os.close(fd); } - } catch (IOException ignored) { + } catch (IOException | ErrnoException e) { + Log.w(TAG, "Exception thrown while closing fd " + fdInt, e); } } } +;
\ No newline at end of file diff --git a/ravenwood/runtime-helper-src/framework/com/android/platform/test/ravenwood/nativesubstitution/Parcel_host.java b/ravenwood/runtime-helper-src/framework/com/android/platform/test/ravenwood/nativesubstitution/Parcel_host.java index 22e11e18ae31..cb00b3e758fa 100644 --- a/ravenwood/runtime-helper-src/framework/com/android/platform/test/ravenwood/nativesubstitution/Parcel_host.java +++ b/ravenwood/runtime-helper-src/framework/com/android/platform/test/ravenwood/nativesubstitution/Parcel_host.java @@ -15,6 +15,11 @@ */ package com.android.platform.test.ravenwood.nativesubstitution; +import android.system.ErrnoException; +import android.system.Os; +import android.util.Log; + +import java.io.FileDescriptor; import java.nio.ByteBuffer; import java.nio.charset.StandardCharsets; import java.util.Arrays; @@ -31,6 +36,8 @@ import java.util.concurrent.atomic.AtomicLong; * {@link ByteBuffer} wouldn't allow...) */ public class Parcel_host { + private static final String TAG = "Parcel"; + private Parcel_host() { } @@ -50,6 +57,11 @@ public class Parcel_host { // TODO Use the actual value from Parcel.java. private static final int OK = 0; + private final Map<Integer, FileDescriptor> mFdMap = new ConcurrentHashMap<>(); + + private static final int FD_PLACEHOLDER = 0xDEADBEEF; + private static final int FD_PAYLOAD_SIZE = 8; + private void validate() { if (mDeleted) { // TODO: Put more info @@ -67,6 +79,7 @@ public class Parcel_host { return p; } + /** Native method substitution */ public static long nativeCreate() { final long id = sNextId.getAndIncrement(); final Parcel_host p = new Parcel_host(); @@ -80,7 +93,8 @@ public class Parcel_host { mSize = 0; mPos = 0; mSensitive = false; - mAllowFds = false; + mAllowFds = true; + mFdMap.clear(); } private void updateSize() { @@ -89,16 +103,19 @@ public class Parcel_host { } } + /** Native method substitution */ public static void nativeDestroy(long nativePtr) { getInstance(nativePtr).mDeleted = true; sInstances.remove(nativePtr); } + /** Native method substitution */ public static void nativeFreeBuffer(long nativePtr) { getInstance(nativePtr).freeBuffer(); } - public void freeBuffer() { + /** Native method substitution */ + private void freeBuffer() { init(); } @@ -137,32 +154,47 @@ public class Parcel_host { } } + /** Native method substitution */ public static void nativeMarkSensitive(long nativePtr) { getInstance(nativePtr).mSensitive = true; } + + /** Native method substitution */ public static int nativeDataSize(long nativePtr) { return getInstance(nativePtr).mSize; } + + /** Native method substitution */ public static int nativeDataAvail(long nativePtr) { var p = getInstance(nativePtr); return p.mSize - p.mPos; } + + /** Native method substitution */ public static int nativeDataPosition(long nativePtr) { return getInstance(nativePtr).mPos; } + + /** Native method substitution */ public static int nativeDataCapacity(long nativePtr) { return getInstance(nativePtr).mBuffer.length; } + + /** Native method substitution */ public static void nativeSetDataSize(long nativePtr, int size) { var p = getInstance(nativePtr); p.ensureCapacity(size); getInstance(nativePtr).mSize = size; } + + /** Native method substitution */ public static void nativeSetDataPosition(long nativePtr, int pos) { var p = getInstance(nativePtr); // TODO: Should this change the size or the capacity?? p.mPos = pos; } + + /** Native method substitution */ public static void nativeSetDataCapacity(long nativePtr, int size) { if (size < 0) { throw new IllegalArgumentException("size < 0: size=" + size); @@ -173,20 +205,25 @@ public class Parcel_host { } } + /** Native method substitution */ public static boolean nativePushAllowFds(long nativePtr, boolean allowFds) { var p = getInstance(nativePtr); var prev = p.mAllowFds; p.mAllowFds = allowFds; return prev; } + + /** Native method substitution */ public static void nativeRestoreAllowFds(long nativePtr, boolean lastValue) { getInstance(nativePtr).mAllowFds = lastValue; } + /** Native method substitution */ public static void nativeWriteByteArray(long nativePtr, byte[] b, int offset, int len) { nativeWriteBlob(nativePtr, b, offset, len); } + /** Native method substitution */ public static void nativeWriteBlob(long nativePtr, byte[] b, int offset, int len) { var p = getInstance(nativePtr); @@ -205,6 +242,7 @@ public class Parcel_host { } } + /** Native method substitution */ public static int nativeWriteInt(long nativePtr, int value) { var p = getInstance(nativePtr); p.ensureMoreCapacity(Integer.BYTES); @@ -219,14 +257,19 @@ public class Parcel_host { return OK; } + /** Native method substitution */ public static int nativeWriteLong(long nativePtr, long value) { nativeWriteInt(nativePtr, (int) (value >>> 32)); nativeWriteInt(nativePtr, (int) (value)); return OK; } + + /** Native method substitution */ public static int nativeWriteFloat(long nativePtr, float val) { return nativeWriteInt(nativePtr, Float.floatToIntBits(val)); } + + /** Native method substitution */ public static int nativeWriteDouble(long nativePtr, double val) { return nativeWriteLong(nativePtr, Double.doubleToLongBits(val)); } @@ -235,6 +278,7 @@ public class Parcel_host { return ((val + 3) / 4) * 4; } + /** Native method substitution */ public static void nativeWriteString8(long nativePtr, String val) { if (val == null) { nativeWriteBlob(nativePtr, null, 0, 0); @@ -243,15 +287,19 @@ public class Parcel_host { nativeWriteBlob(nativePtr, bytes, 0, bytes.length); } } + + /** Native method substitution */ public static void nativeWriteString16(long nativePtr, String val) { // Just reuse String8 nativeWriteString8(nativePtr, val); } + /** Native method substitution */ public static byte[] nativeCreateByteArray(long nativePtr) { return nativeReadBlob(nativePtr); } + /** Native method substitution */ public static boolean nativeReadByteArray(long nativePtr, byte[] dest, int destLen) { if (dest == null) { return false; @@ -271,6 +319,7 @@ public class Parcel_host { return true; } + /** Native method substitution */ public static byte[] nativeReadBlob(long nativePtr) { var p = getInstance(nativePtr); if (p.mSize - p.mPos < 4) { @@ -295,6 +344,8 @@ public class Parcel_host { return bytes; } + + /** Native method substitution */ public static int nativeReadInt(long nativePtr) { var p = getInstance(nativePtr); @@ -310,19 +361,24 @@ public class Parcel_host { return ret; } + + /** Native method substitution */ public static long nativeReadLong(long nativePtr) { return (((long) nativeReadInt(nativePtr)) << 32) | (((long) nativeReadInt(nativePtr)) & 0xffff_ffffL); } + /** Native method substitution */ public static float nativeReadFloat(long nativePtr) { return Float.intBitsToFloat(nativeReadInt(nativePtr)); } + /** Native method substitution */ public static double nativeReadDouble(long nativePtr) { return Double.longBitsToDouble(nativeReadLong(nativePtr)); } + /** Native method substitution */ public static String nativeReadString8(long nativePtr) { final var bytes = nativeReadBlob(nativePtr); if (bytes == null) { @@ -334,10 +390,13 @@ public class Parcel_host { return nativeReadString8(nativePtr); } + /** Native method substitution */ public static byte[] nativeMarshall(long nativePtr) { var p = getInstance(nativePtr); return Arrays.copyOf(p.mBuffer, p.mSize); } + + /** Native method substitution */ public static void nativeUnmarshall( long nativePtr, byte[] data, int offset, int length) { var p = getInstance(nativePtr); @@ -346,6 +405,8 @@ public class Parcel_host { p.mPos += length; p.updateSize(); } + + /** Native method substitution */ public static int nativeCompareData(long thisNativePtr, long otherNativePtr) { var a = getInstance(thisNativePtr); var b = getInstance(otherNativePtr); @@ -355,6 +416,8 @@ public class Parcel_host { return -1; } } + + /** Native method substitution */ public static boolean nativeCompareDataInRange( long ptrA, int offsetA, long ptrB, int offsetB, int length) { var a = getInstance(ptrA); @@ -368,6 +431,8 @@ public class Parcel_host { return Arrays.equals(Arrays.copyOfRange(a.mBuffer, offsetA, offsetA + length), Arrays.copyOfRange(b.mBuffer, offsetB, offsetB + length)); } + + /** Native method substitution */ public static void nativeAppendFrom( long thisNativePtr, long otherNativePtr, int srcOffset, int length) { var dst = getInstance(thisNativePtr); @@ -382,25 +447,84 @@ public class Parcel_host { // TODO: Update the other's position? } - public static boolean nativeHasFileDescriptors(long nativePtr) { - // Assume false for now, because we don't support writing FDs yet. + /** Native method substitution */ + public static boolean nativeHasBinders(long nativePtr) { + // Assume false for now, because we don't support adding binders. return false; } - public static boolean nativeHasFileDescriptorsInRange( + /** Native method substitution */ + public static boolean nativeHasBindersInRange( long nativePtr, int offset, int length) { // Assume false for now, because we don't support writing FDs yet. return false; } - public static boolean nativeHasBinders(long nativePtr) { - // Assume false for now, because we don't support adding binders. - return false; + /** Native method substitution */ + public static void nativeWriteFileDescriptor(long nativePtr, java.io.FileDescriptor val) { + var p = getInstance(nativePtr); + + if (!p.mAllowFds) { + // Simulate the FDS_NOT_ALLOWED case in frameworks/base/core/jni/android_util_Binder.cpp + throw new RuntimeException("Not allowed to write file descriptors here"); + } + + FileDescriptor dup = null; + try { + dup = Os.dup(val); + } catch (ErrnoException e) { + throw new RuntimeException(e); + } + p.mFdMap.put(p.mPos, dup); + + // Parcel.cpp writes two int32s for a FD. + // Make sure FD_PAYLOAD_SIZE is in sync with this code. + nativeWriteInt(nativePtr, FD_PLACEHOLDER); + nativeWriteInt(nativePtr, FD_PLACEHOLDER); } - public static boolean nativeHasBindersInRange( - long nativePtr, int offset, int length) { - // Assume false for now, because we don't support writing FDs yet. + /** Native method substitution */ + public static java.io.FileDescriptor nativeReadFileDescriptor(long nativePtr) { + var p = getInstance(nativePtr); + + var pos = p.mPos; + var fd = p.mFdMap.get(pos); + + if (fd == null) { + Log.w(TAG, "nativeReadFileDescriptor: Not a FD at pos #" + pos); + return null; + } + nativeReadInt(nativePtr); + nativeReadInt(nativePtr); + return fd; + } + + /** Native method substitution */ + public static boolean nativeHasFileDescriptors(long nativePtr) { + var p = getInstance(nativePtr); + return p.mFdMap.size() > 0; + } + + /** Native method substitution */ + public static boolean nativeHasFileDescriptorsInRange(long nativePtr, int offset, int length) { + var p = getInstance(nativePtr); + + // Original code: hasFileDescriptorsInRange() in frameworks/native/libs/binder/Parcel.cpp + if (offset < 0 || length < 0) { + throw new IllegalArgumentException("Negative value not allowed: offset=" + offset + + " length=" + length); + } + long limit = (long) offset + (long) length; + if (limit > p.mSize) { + throw new IllegalArgumentException("Out of range: offset=" + offset + + " length=" + length + " dataSize=" + p.mSize); + } + + for (var pos : p.mFdMap.keySet()) { + if (offset <= pos && (pos + FD_PAYLOAD_SIZE - 1) < (offset + length)) { + return true; + } + } return false; } -} +}
\ No newline at end of file diff --git a/ravenwood/runtime-helper-src/libcore-fake/android/system/Os.java b/ravenwood/runtime-helper-src/libcore-fake/android/system/Os.java index 8a1fe62db4e1..825ab72e773a 100644 --- a/ravenwood/runtime-helper-src/libcore-fake/android/system/Os.java +++ b/ravenwood/runtime-helper-src/libcore-fake/android/system/Os.java @@ -53,4 +53,9 @@ public final class Os { public static StructStat stat(String path) throws ErrnoException { return RavenwoodRuntimeNative.stat(path); } + + /** Ravenwood version of the OS API. */ + public static void close(FileDescriptor fd) throws ErrnoException { + RavenwoodRuntimeNative.close(fd); + } } diff --git a/ravenwood/runtime-helper-src/libcore-fake/com/android/ravenwood/common/RavenwoodRuntimeNative.java b/ravenwood/runtime-helper-src/libcore-fake/com/android/ravenwood/common/RavenwoodRuntimeNative.java index e9b305e5d789..2bc8e7123aad 100644 --- a/ravenwood/runtime-helper-src/libcore-fake/com/android/ravenwood/common/RavenwoodRuntimeNative.java +++ b/ravenwood/runtime-helper-src/libcore-fake/com/android/ravenwood/common/RavenwoodRuntimeNative.java @@ -48,6 +48,8 @@ public class RavenwoodRuntimeNative { public static native StructStat stat(String path) throws ErrnoException; + private static native void nClose(int fd) throws ErrnoException; + public static long lseek(FileDescriptor fd, long offset, int whence) throws ErrnoException { return nLseek(JvmWorkaround.getInstance().getFdInt(fd), offset, whence); } @@ -83,4 +85,11 @@ public class RavenwoodRuntimeNative { return nFstat(fdInt); } + + /** See close(2) */ + public static void close(FileDescriptor fd) throws ErrnoException { + var fdInt = JvmWorkaround.getInstance().getFdInt(fd); + + nClose(fdInt); + } } diff --git a/ravenwood/runtime-jni/ravenwood_runtime.cpp b/ravenwood/runtime-jni/ravenwood_runtime.cpp index e0a3e1c9edf6..ee84954a5c2a 100644 --- a/ravenwood/runtime-jni/ravenwood_runtime.cpp +++ b/ravenwood/runtime-jni/ravenwood_runtime.cpp @@ -167,6 +167,11 @@ static jobject Linux_stat(JNIEnv* env, jobject, jstring javaPath) { return doStat(env, javaPath, false); } +static void nClose(JNIEnv* env, jclass, jint fd) { + // Don't use TEMP_FAILURE_RETRY() on close(): https://lkml.org/lkml/2005/9/10/129 + throwIfMinusOne(env, "close", close(fd)); +} + // ---- Registration ---- static const JNINativeMethod sMethods[] = @@ -179,6 +184,7 @@ static const JNINativeMethod sMethods[] = { "nFstat", "(I)Landroid/system/StructStat;", (void*)nFstat }, { "lstat", "(Ljava/lang/String;)Landroid/system/StructStat;", (void*)Linux_lstat }, { "stat", "(Ljava/lang/String;)Landroid/system/StructStat;", (void*)Linux_stat }, + { "nClose", "(I)V", (void*)nClose }, }; extern "C" jint JNI_OnLoad(JavaVM* vm, void* /* reserved */) diff --git a/ravenwood/texts/ravenwood-annotation-allowed-classes.txt b/ravenwood/texts/ravenwood-annotation-allowed-classes.txt index bdc357789191..68f185eba42c 100644 --- a/ravenwood/texts/ravenwood-annotation-allowed-classes.txt +++ b/ravenwood/texts/ravenwood-annotation-allowed-classes.txt @@ -143,6 +143,7 @@ android.os.Handler android.os.HandlerExecutor android.os.HandlerThread android.os.IBinder +android.os.LocaleList android.os.Looper android.os.Message android.os.MessageQueue diff --git a/services/accessibility/java/com/android/server/accessibility/AccessibilityManagerService.java b/services/accessibility/java/com/android/server/accessibility/AccessibilityManagerService.java index 30c743e508b6..45fcf6b756cf 100644 --- a/services/accessibility/java/com/android/server/accessibility/AccessibilityManagerService.java +++ b/services/accessibility/java/com/android/server/accessibility/AccessibilityManagerService.java @@ -41,6 +41,7 @@ import static android.content.Context.DEVICE_ID_DEFAULT; import static android.provider.Settings.Secure.ACCESSIBILITY_DISPLAY_MAGNIFICATION_NAVBAR_ENABLED; import static android.view.accessibility.AccessibilityManager.FlashNotificationReason; +import static com.android.hardware.input.Flags.keyboardA11yMouseKeys; import static com.android.internal.accessibility.AccessibilityShortcutController.ACCESSIBILITY_HEARING_AIDS_COMPONENT_NAME; import static com.android.internal.accessibility.AccessibilityShortcutController.MAGNIFICATION_COMPONENT_NAME; import static com.android.internal.accessibility.AccessibilityShortcutController.MAGNIFICATION_CONTROLLER_NAME; @@ -57,7 +58,6 @@ import static com.android.internal.accessibility.util.AccessibilityStatsLogUtils import static com.android.internal.util.FunctionalUtils.ignoreRemoteException; import static com.android.internal.util.function.pooled.PooledLambda.obtainMessage; import static com.android.server.accessibility.AccessibilityUserState.doesShortcutTargetsStringContain; -import static com.android.hardware.input.Flags.keyboardA11yMouseKeys; import static com.android.settingslib.RestrictedLockUtils.EnforcedAdmin; import android.accessibilityservice.AccessibilityGestureEvent; @@ -825,25 +825,27 @@ public class AccessibilityManagerService extends IAccessibilityManager.Stub @VisibleForTesting boolean onPackagesForceStoppedLocked( String[] packages, AccessibilityUserState userState) { - final List<String> continuousServicePackages = + final Set<String> packageSet = new HashSet<>(List.of(packages)); + final ArrayList<ComponentName> continuousServices = new ArrayList<>( userState.mInstalledServices.stream().filter(service -> (service.flags & FLAG_REQUEST_ACCESSIBILITY_BUTTON) == FLAG_REQUEST_ACCESSIBILITY_BUTTON - ).map(service -> service.getComponentName().flattenToString()).toList(); + ).map(AccessibilityServiceInfo::getComponentName).toList()); + + // Filter out continuous packages that are not from the array of stopped packages. + continuousServices.removeIf( + continuousName -> !packageSet.contains(continuousName.getPackageName())); boolean enabledServicesChanged = false; final Iterator<ComponentName> it = userState.mEnabledServices.iterator(); while (it.hasNext()) { final ComponentName comp = it.next(); final String compPkg = comp.getPackageName(); - for (String pkg : packages) { - if (compPkg.equals(pkg)) { - it.remove(); - userState.getBindingServicesLocked().remove(comp); - userState.getCrashedServicesLocked().remove(comp); - enabledServicesChanged = true; - break; - } + if (packageSet.contains(compPkg)) { + it.remove(); + userState.getBindingServicesLocked().remove(comp); + userState.getCrashedServicesLocked().remove(comp); + enabledServicesChanged = true; } } if (enabledServicesChanged) { @@ -855,8 +857,8 @@ public class AccessibilityManagerService extends IAccessibilityManager.Stub // Remove any button targets that match any stopped continuous services Set<String> buttonTargets = userState.getShortcutTargetsLocked(SOFTWARE); boolean buttonTargetsChanged = buttonTargets.removeIf( - target -> continuousServicePackages.stream().anyMatch( - pkg -> Objects.equals(target, pkg))); + target -> continuousServices.stream().anyMatch( + continuousName -> continuousName.flattenToString().equals(target))); if (buttonTargetsChanged) { userState.updateShortcutTargetsLocked(buttonTargets, SOFTWARE); persistColonDelimitedSetToSettingLocked( @@ -2641,7 +2643,8 @@ public class AccessibilityManagerService extends IAccessibilityManager.Stub } } - private <T> void persistColonDelimitedSetToSettingLocked(String settingName, int userId, + @VisibleForTesting + <T> void persistColonDelimitedSetToSettingLocked(String settingName, int userId, Set<T> set, Function<T, String> toString) { persistColonDelimitedSetToSettingLocked(settingName, userId, set, toString, /* defaultEmptyString= */ null); @@ -4087,11 +4090,7 @@ public class AccessibilityManagerService extends IAccessibilityManager.Stub boolean enable, @UserShortcutType int shortcutTypes, @NonNull List<String> shortcutTargets, @UserIdInt int userId) { enableShortcutsForTargets_enforcePermission(); - if ((shortcutTypes & GESTURE) == GESTURE - && !android.provider.Flags.a11yStandaloneGestureEnabled()) { - throw new IllegalArgumentException( - "GESTURE type shortcuts are disabled by feature flag"); - } + for (int shortcutType : USER_SHORTCUT_TYPES) { if ((shortcutTypes & shortcutType) == shortcutType) { enableShortcutForTargets(enable, shortcutType, shortcutTargets, userId); @@ -4102,6 +4101,13 @@ public class AccessibilityManagerService extends IAccessibilityManager.Stub private void enableShortcutForTargets( boolean enable, @UserShortcutType int shortcutType, @NonNull List<String> shortcutTargets, @UserIdInt int userId) { + if (shortcutType == UserShortcutType.GESTURE + && !android.provider.Flags.a11yStandaloneGestureEnabled()) { + Slog.w(LOG_TAG, + "GESTURE type shortcuts are disabled by feature flag"); + return; + } + final String shortcutTypeSettingKey = ShortcutUtils.convertToKey(shortcutType); if (shortcutType == UserShortcutType.TRIPLETAP || shortcutType == UserShortcutType.TWOFINGER_DOUBLETAP) { diff --git a/services/accessibility/java/com/android/server/accessibility/a11ychecker/AccessibilityCheckerManager.java b/services/accessibility/java/com/android/server/accessibility/a11ychecker/AccessibilityCheckerManager.java index 8a2bc1dbf4f7..f7a59a4b2763 100644 --- a/services/accessibility/java/com/android/server/accessibility/a11ychecker/AccessibilityCheckerManager.java +++ b/services/accessibility/java/com/android/server/accessibility/a11ychecker/AccessibilityCheckerManager.java @@ -26,7 +26,6 @@ import android.content.ComponentName; import android.content.Context; import android.content.pm.PackageManager; import android.util.Slog; -import android.view.accessibility.AccessibilityEvent; import android.view.accessibility.AccessibilityNodeInfo; import com.android.internal.annotations.VisibleForTesting; @@ -60,6 +59,7 @@ public final class AccessibilityCheckerManager { private final Set<AccessibilityHierarchyCheck> mHierarchyChecks; private final ATFHierarchyBuilder mATFHierarchyBuilder; private final Set<AccessibilityCheckResultReported> mCachedResults = new HashSet<>(); + @VisibleForTesting final A11yCheckerTimer mTimer = new A11yCheckerTimer(); @@ -86,10 +86,8 @@ public final class AccessibilityCheckerManager { */ @RequiresPermission(allOf = {android.Manifest.permission.INTERACT_ACROSS_USERS_FULL}) public Set<AccessibilityCheckResultReported> maybeRunA11yChecker( - List<AccessibilityNodeInfo> nodes, - @Nullable AccessibilityEvent accessibilityEvent, - ComponentName sourceComponentName, - @UserIdInt int userId) { + List<AccessibilityNodeInfo> nodes, @Nullable String sourceEventClassName, + ComponentName a11yServiceComponentName, @UserIdInt int userId) { if (!shouldRunA11yChecker()) { return Set.of(); } @@ -108,14 +106,13 @@ public final class AccessibilityCheckerManager { List<AccessibilityHierarchyCheckResult> checkResults = runChecksOnNode(nodeInfo); Set<AccessibilityCheckResultReported> filteredResults = AccessibilityCheckerUtils.processResults(nodeInfo, checkResults, - accessibilityEvent, mPackageManager, sourceComponentName); + sourceEventClassName, mPackageManager, a11yServiceComponentName); allResults.addAll(filteredResults); } mCachedResults.addAll(allResults); } catch (RuntimeException e) { Slog.e(LOG_TAG, "An unknown error occurred while running a11y checker.", e); } - return allResults; } diff --git a/services/accessibility/java/com/android/server/accessibility/a11ychecker/AccessibilityCheckerUtils.java b/services/accessibility/java/com/android/server/accessibility/a11ychecker/AccessibilityCheckerUtils.java index 4171108770a9..fa0fed245e0d 100644 --- a/services/accessibility/java/com/android/server/accessibility/a11ychecker/AccessibilityCheckerUtils.java +++ b/services/accessibility/java/com/android/server/accessibility/a11ychecker/AccessibilityCheckerUtils.java @@ -22,7 +22,6 @@ import android.content.ComponentName; import android.content.pm.PackageInfo; import android.content.pm.PackageManager; import android.util.Slog; -import android.view.accessibility.AccessibilityEvent; import android.view.accessibility.AccessibilityNodeInfo; import com.android.internal.annotations.VisibleForTesting; @@ -96,7 +95,7 @@ public class AccessibilityCheckerUtils { static Set<AccessibilityCheckResultReported> processResults( AccessibilityNodeInfo nodeInfo, List<AccessibilityHierarchyCheckResult> checkResults, - @Nullable AccessibilityEvent accessibilityEvent, + @Nullable String activityClassName, PackageManager packageManager, ComponentName a11yServiceComponentName) { String appPackageName = nodeInfo.getPackageName().toString(); @@ -110,7 +109,8 @@ public class AccessibilityCheckerUtils { .setPackageName(appPackageName) .setAppVersionCode(getAppVersionCode(packageManager, appPackageName)) .setUiElementPath(nodePath) - .setActivityName(getActivityName(packageManager, accessibilityEvent)) + .setActivityName( + getActivityName(packageManager, appPackageName, activityClassName)) .setWindowTitle(getWindowTitle(nodeInfo)) .setSourceComponentName(a11yServiceComponentName.flattenToString()) .setSourceVersionCode( @@ -140,31 +140,23 @@ public class AccessibilityCheckerUtils { } /** - * Returns the simple class name of the Activity providing the cache update, if available, + * Returns the simple class name of the Activity associated with the window, if available, * or an empty String if not. */ @VisibleForTesting static String getActivityName( - PackageManager packageManager, @Nullable AccessibilityEvent accessibilityEvent) { - if (accessibilityEvent == null) { + PackageManager packageManager, String packageName, @Nullable String activityClassName) { + if (activityClassName == null) { return ""; } - CharSequence activityName = accessibilityEvent.getClassName(); - if (accessibilityEvent.getEventType() == AccessibilityEvent.TYPE_WINDOW_STATE_CHANGED - && accessibilityEvent.getPackageName() != null - && activityName != null) { - try { - // Check class is for a valid Activity. - packageManager - .getActivityInfo( - new ComponentName(accessibilityEvent.getPackageName().toString(), - activityName.toString()), 0); - int qualifierEnd = activityName.toString().lastIndexOf('.'); - return activityName.toString().substring(qualifierEnd + 1); - } catch (PackageManager.NameNotFoundException e) { - // No need to spam the logs. This is very frequent when the class doesn't match - // an activity. - } + try { + // Check class is for a valid Activity. + packageManager.getActivityInfo(new ComponentName(packageName, activityClassName), 0); + int qualifierEnd = activityClassName.lastIndexOf('.'); + return activityClassName.substring(qualifierEnd + 1); + } catch (PackageManager.NameNotFoundException e) { + // No need to spam the logs. This is very frequent when the class doesn't match + // an activity. } return ""; } diff --git a/services/accessibility/java/com/android/server/accessibility/magnification/FullScreenMagnificationGestureHandler.java b/services/accessibility/java/com/android/server/accessibility/magnification/FullScreenMagnificationGestureHandler.java index e9c3fbdf021c..0ee58967c9b7 100644 --- a/services/accessibility/java/com/android/server/accessibility/magnification/FullScreenMagnificationGestureHandler.java +++ b/services/accessibility/java/com/android/server/accessibility/magnification/FullScreenMagnificationGestureHandler.java @@ -523,6 +523,7 @@ public class FullScreenMagnificationGestureHandler extends MagnificationGestureH mScaleGestureDetector = new ScaleGestureDetector(context, this, Handler.getMain()); mScaleGestureDetector.setQuickScaleEnabled(false); mScrollGestureDetector = new GestureDetector(context, this, Handler.getMain()); + mScrollGestureDetector.setIsLongpressEnabled(false); } @Override @@ -1658,11 +1659,12 @@ public class FullScreenMagnificationGestureHandler extends MagnificationGestureH } float dX = event.getX() - firstPointerDownLocation.x; float dY = event.getY() - firstPointerDownLocation.y; - if (isAtLeftEdge() && dX > 0) { + if (isAtLeftEdge() && isScrollingLeft(dX, dY)) { return OVERSCROLL_LEFT_EDGE; - } else if (isAtRightEdge() && dX < 0) { + } else if (isAtRightEdge() && isScrollingRight(dX, dY)) { return OVERSCROLL_RIGHT_EDGE; - } else if ((isAtTopEdge() && dY > 0) || (isAtBottomEdge() && dY < 0)) { + } else if ((isAtTopEdge() && isScrollingUp(dX, dY)) + || (isAtBottomEdge() && isScrollingDown(dX, dY))) { return OVERSCROLL_VERTICAL_EDGE; } return OVERSCROLL_NONE; @@ -1672,18 +1674,34 @@ public class FullScreenMagnificationGestureHandler extends MagnificationGestureH return mFullScreenMagnificationController.isAtLeftEdge(mDisplayId, mOverscrollEdgeSlop); } + private static boolean isScrollingLeft(float dX, float dY) { + return Math.abs(dX) > Math.abs(dY) && dX > 0; + } + private boolean isAtRightEdge() { return mFullScreenMagnificationController.isAtRightEdge(mDisplayId, mOverscrollEdgeSlop); } + private static boolean isScrollingRight(float dX, float dY) { + return Math.abs(dX) > Math.abs(dY) && dX < 0; + } + private boolean isAtTopEdge() { return mFullScreenMagnificationController.isAtTopEdge(mDisplayId, mOverscrollEdgeSlop); } + private static boolean isScrollingUp(float dX, float dY) { + return Math.abs(dX) < Math.abs(dY) && dY > 0; + } + private boolean isAtBottomEdge() { return mFullScreenMagnificationController.isAtBottomEdge(mDisplayId, mOverscrollEdgeSlop); } + private static boolean isScrollingDown(float dX, float dY) { + return Math.abs(dX) < Math.abs(dY) && dY < 0; + } + private boolean pointerValid(PointF pointerDownLocation) { return !(Float.isNaN(pointerDownLocation.x) && Float.isNaN(pointerDownLocation.y)); } @@ -1876,6 +1894,7 @@ public class FullScreenMagnificationGestureHandler extends MagnificationGestureH private MotionEventInfo mEvent; SinglePanningState(Context context) { mScrollGestureDetector = new GestureDetector(context, this, Handler.getMain()); + mScrollGestureDetector.setIsLongpressEnabled(false); } @Override diff --git a/services/autofill/java/com/android/server/autofill/AutofillManagerService.java b/services/autofill/java/com/android/server/autofill/AutofillManagerService.java index eae516e10d6e..9f7fb5710bcc 100644 --- a/services/autofill/java/com/android/server/autofill/AutofillManagerService.java +++ b/services/autofill/java/com/android/server/autofill/AutofillManagerService.java @@ -1985,12 +1985,13 @@ public final class AutofillManagerService } @Override - public void setAutofillFailure(int sessionId, @NonNull List<AutofillId> ids, int userId) { + public void setAutofillFailure( + int sessionId, @NonNull List<AutofillId> ids, boolean isRefill, int userId) { synchronized (mLock) { final AutofillManagerServiceImpl service = peekServiceForUserWithLocalBinderIdentityLocked(userId); if (service != null) { - service.setAutofillFailureLocked(sessionId, getCallingUid(), ids); + service.setAutofillFailureLocked(sessionId, getCallingUid(), ids, isRefill); } else if (sVerbose) { Slog.v(TAG, "setAutofillFailure(): no service for " + userId); } @@ -2011,6 +2012,46 @@ public final class AutofillManagerService } @Override + public void notifyNotExpiringResponseDuringAuth(int sessionId, int userId) { + synchronized (mLock) { + final AutofillManagerServiceImpl service = + peekServiceForUserWithLocalBinderIdentityLocked(userId); + if (service != null) { + service.notifyNotExpiringResponseDuringAuth(sessionId, getCallingUid()); + } else if (sVerbose) { + Slog.v(TAG, "notifyNotExpiringResponseDuringAuth(): no service for " + userId); + } + } + } + + @Override + public void notifyViewEnteredIgnoredDuringAuthCount(int sessionId, int userId) { + synchronized (mLock) { + final AutofillManagerServiceImpl service = + peekServiceForUserWithLocalBinderIdentityLocked(userId); + if (service != null) { + service.notifyViewEnteredIgnoredDuringAuthCount(sessionId, getCallingUid()); + } else if (sVerbose) { + Slog.v(TAG, "notifyNotExpiringResponseDuringAuth(): no service for " + userId); + } + } + } + + @Override + public void setAutofillIdsAttemptedForRefill( + int sessionId, @NonNull List<AutofillId> ids, int userId) { + synchronized (mLock) { + final AutofillManagerServiceImpl service = + peekServiceForUserWithLocalBinderIdentityLocked(userId); + if (service != null) { + service.setAutofillIdsAttemptedForRefill(sessionId, ids, getCallingUid()); + } else if (sVerbose) { + Slog.v(TAG, "setAutofillIdsAttemptedForRefill(): no service for " + userId); + } + } + } + + @Override public void finishSession(int sessionId, int userId, @AutofillCommitReason int commitReason) { synchronized (mLock) { diff --git a/services/autofill/java/com/android/server/autofill/AutofillManagerServiceImpl.java b/services/autofill/java/com/android/server/autofill/AutofillManagerServiceImpl.java index 2bf319e06efa..c9f892907b59 100644 --- a/services/autofill/java/com/android/server/autofill/AutofillManagerServiceImpl.java +++ b/services/autofill/java/com/android/server/autofill/AutofillManagerServiceImpl.java @@ -464,7 +464,8 @@ final class AutofillManagerServiceImpl } @GuardedBy("mLock") - void setAutofillFailureLocked(int sessionId, int uid, @NonNull List<AutofillId> ids) { + void setAutofillFailureLocked( + int sessionId, int uid, @NonNull List<AutofillId> ids, boolean isRefill) { if (!isEnabledLocked()) { Slog.wtf(TAG, "Service not enabled"); return; @@ -474,7 +475,7 @@ final class AutofillManagerServiceImpl Slog.v(TAG, "setAutofillFailure(): no session for " + sessionId + "(" + uid + ")"); return; } - session.setAutofillFailureLocked(ids); + session.setAutofillFailureLocked(ids, isRefill); } @GuardedBy("mLock") @@ -492,6 +493,52 @@ final class AutofillManagerServiceImpl } @GuardedBy("mLock") + void notifyNotExpiringResponseDuringAuth(int sessionId, int uid) { + if (!isEnabledLocked()) { + Slog.wtf(TAG, "Service not enabled"); + return; + } + final Session session = mSessions.get(sessionId); + if (session == null || uid != session.uid) { + Slog.v(TAG, "notifyNotExpiringResponseDuringAuth(): no session for " + + sessionId + "(" + uid + ")"); + return; + } + session.setNotifyNotExpiringResponseDuringAuth(); + } + + @GuardedBy("mLock") + void notifyViewEnteredIgnoredDuringAuthCount(int sessionId, int uid) { + if (!isEnabledLocked()) { + Slog.wtf(TAG, "Service not enabled"); + return; + } + final Session session = mSessions.get(sessionId); + if (session == null || uid != session.uid) { + Slog.v(TAG, "notifyViewEnteredIgnoredDuringAuthCount(): no session for " + + sessionId + "(" + uid + ")"); + return; + } + session.setLogViewEnteredIgnoredDuringAuth(); + } + + @GuardedBy("mLock") + public void setAutofillIdsAttemptedForRefill( + int sessionId, @NonNull List<AutofillId> ids, int uid) { + if (!isEnabledLocked()) { + Slog.wtf(TAG, "Service not enabled"); + return; + } + final Session session = mSessions.get(sessionId); + if (session == null || uid != session.uid) { + Slog.v(TAG, "setAutofillIdsAttemptedForRefill(): no session for " + + sessionId + "(" + uid + ")"); + return; + } + session.setAutofillIdsAttemptedForRefillLocked(ids); + } + + @GuardedBy("mLock") void finishSessionLocked(int sessionId, int uid, @AutofillCommitReason int commitReason) { if (!isEnabledLocked()) { Slog.wtf(TAG, "Service not enabled"); diff --git a/services/autofill/java/com/android/server/autofill/PresentationStatsEventLogger.java b/services/autofill/java/com/android/server/autofill/PresentationStatsEventLogger.java index 49ca29745b11..930af5e7f056 100644 --- a/services/autofill/java/com/android/server/autofill/PresentationStatsEventLogger.java +++ b/services/autofill/java/com/android/server/autofill/PresentationStatsEventLogger.java @@ -58,6 +58,7 @@ import static com.android.internal.util.FrameworkStatsLog.AUTOFILL_PRESENTATION_ import static com.android.server.autofill.Helper.sVerbose; import android.annotation.IntDef; +import android.annotation.NonNull; import android.annotation.Nullable; import android.content.ComponentName; import android.content.Context; @@ -685,6 +686,19 @@ public final class PresentationStatsEventLogger { } /** + * Set views_fillable_total_count as long as mEventInternal presents. + */ + public void maybeUpdateViewFillablesForRefillAttempt(List<AutofillId> autofillIds) { + mEventInternal.ifPresent(event -> { + // These autofill ids would be the ones being re-attempted. + event.mAutofillIdsAttemptedAutofill = new ArraySet<>(autofillIds); + // These autofill id's are being refilled, so they had failed previously. + // Note that these autofillIds correspond to the new autofill ids after relayout. + event.mFailedAutofillIds = new ArraySet<>(autofillIds); + }); + } + + /** * Set how many views are filtered from fill because they are not in current session */ public void maybeSetFilteredFillableViewsCount(int filteredViewsCount) { @@ -697,9 +711,16 @@ public final class PresentationStatsEventLogger { * Set views_filled_failure_count using failure count as long as mEventInternal * presents. */ - public void maybeSetViewFillFailureCounts(int failureCount) { + public void maybeSetViewFillFailureCounts(@NonNull List<AutofillId> ids, boolean isRefill) { mEventInternal.ifPresent(event -> { - event.mViewFillFailureCount = failureCount; + int failureCount = ids.size(); + if (isRefill) { + event.mViewFailedOnRefillCount = failureCount; + } else { + event.mViewFillFailureCount = failureCount; + event.mViewFailedPriorToRefillCount = failureCount; + event.mFailedAutofillIds = new ArraySet<>(ids); + } }); } @@ -719,7 +740,7 @@ public final class PresentationStatsEventLogger { * Set views_filled_failure_count using failure count as long as mEventInternal * presents. */ - public void maybeAddSuccessId(AutofillId autofillId) { + public synchronized void maybeAddSuccessId(AutofillId autofillId) { mEventInternal.ifPresent(event -> { ArraySet<AutofillId> autofillIds = event.mAutofillIdsAttemptedAutofill; if (autofillIds == null) { @@ -727,9 +748,21 @@ public final class PresentationStatsEventLogger { + " successfully filled"); event.mViewFilledButUnexpectedCount++; } else if (autofillIds.contains(autofillId)) { - if (sVerbose) { - Slog.v(TAG, "Logging autofill for id:" + autofillId); + ArraySet<AutofillId> failedIds = event.mFailedAutofillIds; + if (failedIds.contains(autofillId)) { + if (sVerbose) { + Slog.v(TAG, "Logging autofill refill of id:" + autofillId); + } + // This indicates the success after refill attempt + event.mViewFilledSuccessfullyOnRefillCount++; + // Remove so if we don't reprocess duplicate requests + failedIds.remove(autofillId); + } else { + if (sVerbose) { + Slog.v(TAG, "Logging autofill for id:" + autofillId); + } } + // Common actions to take irrespective of being filled by refill attempt or not. event.mViewFillSuccessCount++; autofillIds.remove(autofillId); event.mAlreadyFilledAutofillIds.add(autofillId); @@ -746,6 +779,23 @@ public final class PresentationStatsEventLogger { }); } + /** + * Set how many views are filtered from fill because they are not in current session + */ + public void maybeSetNotifyNotExpiringResponseDuringAuth() { + mEventInternal.ifPresent(event -> { + event.mFixExpireResponseDuringAuthCount++; + }); + } + /** + * Set how many views are filtered from fill because they are not in current session + */ + public void notifyViewEnteredIgnoredDuringAuthCount() { + mEventInternal.ifPresent(event -> { + event.mNotifyViewEnteredIgnoredDuringAuthCount++; + }); + } + public void logAndEndEvent() { if (!mEventInternal.isPresent()) { Slog.w(TAG, "Shouldn't be logging AutofillPresentationEventReported again for same " @@ -933,6 +983,7 @@ public final class PresentationStatsEventLogger { int mNotifyViewEnteredIgnoredDuringAuthCount = 0; ArraySet<AutofillId> mAutofillIdsAttemptedAutofill; + ArraySet<AutofillId> mFailedAutofillIds = new ArraySet<>(); ArraySet<AutofillId> mAlreadyFilledAutofillIds = new ArraySet<>(); // Not logged - used for internal logic diff --git a/services/autofill/java/com/android/server/autofill/Session.java b/services/autofill/java/com/android/server/autofill/Session.java index 21df7a5487ef..b7508b4f07b7 100644 --- a/services/autofill/java/com/android/server/autofill/Session.java +++ b/services/autofill/java/com/android/server/autofill/Session.java @@ -5360,6 +5360,8 @@ final class Session implements RemoteFillService.FillServiceCallbacks, ViewState saveTriggerId = null; } + boolean hasAuthentication = (response.getAuthentication() != null); + // Must also track that are part of datasets, otherwise the FillUI won't be hidden when // they go away (if they're not savable). @@ -5379,6 +5381,9 @@ final class Session implements RemoteFillService.FillServiceCallbacks, ViewState } } } + if (dataset.getAuthentication() != null) { + hasAuthentication = true; + } } } @@ -5390,7 +5395,7 @@ final class Session implements RemoteFillService.FillServiceCallbacks, ViewState + " hasSaveInfo: " + (saveInfo != null)); } mClient.setTrackedViews(id, toArray(trackedViews), mSaveOnAllViewsInvisible, - saveOnFinish, toArray(fillableIds), saveTriggerId); + saveOnFinish, toArray(fillableIds), saveTriggerId, hasAuthentication); } catch (RemoteException e) { Slog.w(TAG, "Cannot set tracked ids", e); } @@ -5400,7 +5405,7 @@ final class Session implements RemoteFillService.FillServiceCallbacks, ViewState * Sets the state of views that failed to autofill. */ @GuardedBy("mLock") - void setAutofillFailureLocked(@NonNull List<AutofillId> ids) { + void setAutofillFailureLocked(@NonNull List<AutofillId> ids, boolean isRefill) { if (sVerbose && !ids.isEmpty()) { Slog.v(TAG, "Total views that failed to populate: " + ids.size()); } @@ -5418,7 +5423,7 @@ final class Session implements RemoteFillService.FillServiceCallbacks, ViewState Slog.v(TAG, "Changed state of " + id + " to " + viewState.getStateAsString()); } } - mPresentationStatsEventLogger.maybeSetViewFillFailureCounts(ids.size()); + mPresentationStatsEventLogger.maybeSetViewFillFailureCounts(ids, isRefill); } /** @@ -5435,6 +5440,23 @@ final class Session implements RemoteFillService.FillServiceCallbacks, ViewState mPresentationStatsEventLogger.maybeAddSuccessId(id); } + /** + * Sets the state of views that failed to autofill. + */ + void setNotifyNotExpiringResponseDuringAuth() { + synchronized (mLock) { + mPresentationStatsEventLogger.maybeSetNotifyNotExpiringResponseDuringAuth(); + } + } + /** + * Sets the state of views that failed to autofill. + */ + void setLogViewEnteredIgnoredDuringAuth() { + synchronized (mLock) { + mPresentationStatsEventLogger.notifyViewEnteredIgnoredDuringAuthCount(); + } + } + @GuardedBy("mLock") private void replaceResponseLocked(@NonNull FillResponse oldResponse, @NonNull FillResponse newResponse, @Nullable Bundle newClientState) { @@ -6665,6 +6687,11 @@ final class Session implements RemoteFillService.FillServiceCallbacks, ViewState } } + @GuardedBy("mLock") + public void setAutofillIdsAttemptedForRefillLocked(@NonNull List<AutofillId> ids) { + mPresentationStatsEventLogger.maybeUpdateViewFillablesForRefillAttempt(ids); + } + private AutoFillUI getUiForShowing() { synchronized (mLock) { mUi.setCallback(this); diff --git a/services/core/java/com/android/server/accounts/AccountManagerService.java b/services/core/java/com/android/server/accounts/AccountManagerService.java index 69478bbd0d44..2af5316fb352 100644 --- a/services/core/java/com/android/server/accounts/AccountManagerService.java +++ b/services/core/java/com/android/server/accounts/AccountManagerService.java @@ -186,6 +186,12 @@ public class AccountManagerService final Context mContext; + private static final int[] INTERESTING_APP_OPS = new int[] { + AppOpsManager.OP_GET_ACCOUNTS, + AppOpsManager.OP_READ_CONTACTS, + AppOpsManager.OP_WRITE_CONTACTS, + }; + private final PackageManager mPackageManager; private final AppOpsManager mAppOpsManager; private UserManager mUserManager; @@ -389,74 +395,48 @@ public class AccountManagerService }.register(mContext, mHandler.getLooper(), UserHandle.ALL, true); // Cancel account request notification if an app op was preventing the account access - mAppOpsManager.startWatchingMode(AppOpsManager.OP_GET_ACCOUNTS, null, - new AppOpsManager.OnOpChangedInternalListener() { - @Override - public void onOpChanged(int op, String packageName) { - try { - final int userId = ActivityManager.getCurrentUser(); - final int uid = mPackageManager.getPackageUidAsUser(packageName, userId); - final int mode = mAppOpsManager.checkOpNoThrow( - AppOpsManager.OP_GET_ACCOUNTS, uid, packageName); - if (mode == AppOpsManager.MODE_ALLOWED) { - final long identity = Binder.clearCallingIdentity(); - try { - UserAccounts accounts = getUserAccounts(userId); - cancelAccountAccessRequestNotificationIfNeeded( - packageName, uid, true, accounts); - } finally { - Binder.restoreCallingIdentity(identity); - } - } - } catch (NameNotFoundException e) { - /* ignore */ - } catch (SQLiteCantOpenDatabaseException e) { - Log.w(TAG, "Can't read accounts database", e); - return; - } - } - }); + for (int i = 0; i < INTERESTING_APP_OPS.length; ++i) { + mAppOpsManager.startWatchingMode(INTERESTING_APP_OPS[i], null, + new OnInterestingAppOpChangedListener()); + } - // Cancel account request notification if a permission was preventing the account access - mPackageManager.addOnPermissionsChangeListener( - (int uid) -> { - // Permission changes cause requires updating accounts cache. + // Clear the accounts cache on permission changes. + // The specific permissions we care about are backed by AppOps, so just + // let the change events on those handle clearing any notifications. + mPackageManager.addOnPermissionsChangeListener((int uid) -> { AccountManager.invalidateLocalAccountsDataCaches(); + }); + } - Account[] accounts = null; - String[] packageNames = mPackageManager.getPackagesForUid(uid); - if (packageNames != null) { - final int userId = UserHandle.getUserId(uid); - final long identity = Binder.clearCallingIdentity(); - try { - for (String packageName : packageNames) { - // if app asked for permission we need to cancel notification even - // for O+ applications. - if (mPackageManager.checkPermission( - Manifest.permission.GET_ACCOUNTS, - packageName) != PackageManager.PERMISSION_GRANTED) { - continue; - } + private class OnInterestingAppOpChangedListener + extends AppOpsManager.OnOpChangedInternalListener { + @Override + public void onOpChanged(int op, String packageName) { + final int userId = ActivityManager.getCurrentUser(); + final int packageUid; + try { + packageUid = mPackageManager.getPackageUidAsUser(packageName, userId); + } catch (NameNotFoundException e) { + /* ignore */ + return; + } - if (accounts == null) { - accounts = getAccountsOrEmptyArray(null, userId, "android"); - if (ArrayUtils.isEmpty(accounts)) { - return; - } - } - UserAccounts userAccounts = getUserAccounts(UserHandle.getUserId(uid)); - for (Account account : accounts) { - cancelAccountAccessRequestNotificationIfNeeded( - account, uid, packageName, true, userAccounts); - } - } - } finally { - Binder.restoreCallingIdentity(identity); - } + final int mode = mAppOpsManager.checkOpNoThrow(op, packageUid, packageName); + if (mode != AppOpsManager.MODE_ALLOWED) { + return; } - }); - } + final long identity = Binder.clearCallingIdentity(); + try { + cancelAccountAccessRequestNotificationIfNeeded( + packageName, packageUid, true, getUserAccounts(userId)); + } catch (SQLiteCantOpenDatabaseException e) { + Log.w(TAG, "Can't read accounts database", e); + } finally { + Binder.restoreCallingIdentity(identity); + } + } + } boolean getBindInstantServiceAllowed(int userId) { return mAuthenticatorCache.getBindInstantServiceAllowed(userId); diff --git a/services/core/java/com/android/server/am/ActiveServices.java b/services/core/java/com/android/server/am/ActiveServices.java index 0fa5260a2e89..2e1416b2887b 100644 --- a/services/core/java/com/android/server/am/ActiveServices.java +++ b/services/core/java/com/android/server/am/ActiveServices.java @@ -6653,9 +6653,10 @@ public final class ActiveServices { // If unbound while waiting to start and there is no connection left in this service, // remove the pending service - if (s.getConnections().isEmpty()) { + if (s.getConnections().isEmpty() && !s.startRequested) { mPendingServices.remove(s); mPendingBringups.remove(s); + if (DEBUG_SERVICE) Slog.v(TAG_SERVICE, "Removed pending service: " + s); } if (c.hasFlag(Context.BIND_AUTO_CREATE)) { diff --git a/services/core/java/com/android/server/am/BatteryStatsService.java b/services/core/java/com/android/server/am/BatteryStatsService.java index e46ab8f0f1cb..03fbfd37cbdb 100644 --- a/services/core/java/com/android/server/am/BatteryStatsService.java +++ b/services/core/java/com/android/server/am/BatteryStatsService.java @@ -144,6 +144,7 @@ import com.android.server.power.stats.PowerStatsScheduler; import com.android.server.power.stats.PowerStatsStore; import com.android.server.power.stats.PowerStatsUidResolver; import com.android.server.power.stats.ScreenPowerStatsProcessor; +import com.android.server.power.stats.SensorPowerStatsProcessor; import com.android.server.power.stats.SystemServerCpuThreadReader.SystemServiceCpuThreadTimes; import com.android.server.power.stats.VideoPowerStatsProcessor; import com.android.server.power.stats.WifiPowerStatsProcessor; @@ -595,6 +596,17 @@ public final class BatteryStatsService extends IBatteryStats.Stub .setProcessor( new GnssPowerStatsProcessor(mPowerProfile, mPowerStatsUidResolver)); + config.trackPowerComponent(BatteryConsumer.POWER_COMPONENT_SENSORS) + .trackDeviceStates( + AggregatedPowerStatsConfig.STATE_POWER, + AggregatedPowerStatsConfig.STATE_SCREEN) + .trackUidStates( + AggregatedPowerStatsConfig.STATE_POWER, + AggregatedPowerStatsConfig.STATE_SCREEN, + AggregatedPowerStatsConfig.STATE_PROCESS_STATE) + .setProcessor(new SensorPowerStatsProcessor( + () -> mContext.getSystemService(SensorManager.class))); + config.trackCustomPowerComponents(CustomEnergyConsumerPowerStatsProcessor::new) .trackDeviceStates( AggregatedPowerStatsConfig.STATE_POWER, @@ -706,6 +718,10 @@ public final class BatteryStatsService extends IBatteryStats.Stub BatteryConsumer.POWER_COMPONENT_GNSS, Flags.streamlinedMiscBatteryStats()); + mBatteryUsageStatsProvider.setPowerStatsExporterEnabled( + BatteryConsumer.POWER_COMPONENT_SENSORS, + Flags.streamlinedMiscBatteryStats()); + mStats.setPowerStatsCollectorEnabled(BatteryConsumer.POWER_COMPONENT_CAMERA, Flags.streamlinedMiscBatteryStats()); mBatteryUsageStatsProvider.setPowerStatsExporterEnabled( diff --git a/services/core/java/com/android/server/am/ContentProviderHelper.java b/services/core/java/com/android/server/am/ContentProviderHelper.java index 4ff13679ed5c..afb7bb447be1 100644 --- a/services/core/java/com/android/server/am/ContentProviderHelper.java +++ b/services/core/java/com/android/server/am/ContentProviderHelper.java @@ -538,6 +538,8 @@ public class ContentProviderHelper { if (!pr.hasProvider(cpi.name)) { checkTime(startTime, "getContentProviderImpl: scheduling install"); pr.installProvider(cpi.name, cpr); + mService.mOomAdjuster.unfreezeTemporarily(proc, + CachedAppOptimizer.UNFREEZE_REASON_GET_PROVIDER); try { thread.scheduleInstallProvider(cpi); } catch (RemoteException e) { diff --git a/services/core/java/com/android/server/am/PendingIntentController.java b/services/core/java/com/android/server/am/PendingIntentController.java index f3361203c44a..3b0147cb665d 100644 --- a/services/core/java/com/android/server/am/PendingIntentController.java +++ b/services/core/java/com/android/server/am/PendingIntentController.java @@ -149,21 +149,6 @@ public class PendingIntentController { ActivityOptions.MODE_BACKGROUND_ACTIVITY_START_SYSTEM_DEFINED); } - if (opts != null && opts.isPendingIntentBackgroundActivityLaunchAllowedByPermission()) { - Slog.wtf(TAG, - "Resetting option pendingIntentBackgroundActivityLaunchAllowedByPermission" - + " which is set by the pending intent creator (" - + packageName - + ") because this option is meant for the pending intent sender"); - if (CompatChanges.isChangeEnabled(PendingIntent.PENDING_INTENT_OPTIONS_CHECK, - callingUid)) { - throw new IllegalArgumentException( - "pendingIntentBackgroundActivityLaunchAllowedByPermission " - + "can not be set by creator of a PendingIntent"); - } - opts.setPendingIntentBackgroundActivityLaunchAllowedByPermission(false); - } - final boolean noCreate = (flags & PendingIntent.FLAG_NO_CREATE) != 0; final boolean cancelCurrent = (flags & PendingIntent.FLAG_CANCEL_CURRENT) != 0; final boolean updateCurrent = (flags & PendingIntent.FLAG_UPDATE_CURRENT) != 0; diff --git a/services/core/java/com/android/server/am/SettingsToPropertiesMapper.java b/services/core/java/com/android/server/am/SettingsToPropertiesMapper.java index 7f43fae72d60..31232687418f 100644 --- a/services/core/java/com/android/server/am/SettingsToPropertiesMapper.java +++ b/services/core/java/com/android/server/am/SettingsToPropertiesMapper.java @@ -174,6 +174,7 @@ public class SettingsToPropertiesMapper { "haptics", "hardware_backed_security_mainline", "input", + "incremental", "llvm_and_toolchains", "lse_desktop_experience", "machine_learning", diff --git a/services/core/java/com/android/server/appop/AttributedOp.java b/services/core/java/com/android/server/appop/AttributedOp.java index 8cf47d02abb2..430be035737a 100644 --- a/services/core/java/com/android/server/appop/AttributedOp.java +++ b/services/core/java/com/android/server/appop/AttributedOp.java @@ -109,7 +109,7 @@ final class AttributedOp { uidState, flags); mAppOpsService.mHistoricalRegistry.incrementOpAccessedCount(parent.op, parent.uid, - parent.packageName, tag, uidState, flags, accessTime, + parent.packageName, persistentDeviceId, tag, uidState, flags, accessTime, AppOpsManager.ATTRIBUTION_FLAGS_NONE, AppOpsManager.ATTRIBUTION_CHAIN_ID_NONE); } @@ -253,8 +253,8 @@ final class AttributedOp { if (isStarted) { mAppOpsService.mHistoricalRegistry.incrementOpAccessedCount(parent.op, parent.uid, - parent.packageName, tag, uidState, flags, startTime, attributionFlags, - attributionChainId); + parent.packageName, persistentDeviceId, tag, uidState, flags, startTime, + attributionFlags, attributionChainId); } } @@ -333,7 +333,7 @@ final class AttributedOp { finishedEvent); mAppOpsService.mHistoricalRegistry.increaseOpAccessDuration(parent.op, parent.uid, - parent.packageName, tag, event.getUidState(), + parent.packageName, persistentDeviceId, tag, event.getUidState(), event.getFlags(), finishedEvent.getNoteTime(), finishedEvent.getDuration(), event.getAttributionFlags(), event.getAttributionChainId()); @@ -441,8 +441,9 @@ final class AttributedOp { event.setStartElapsedTime(SystemClock.elapsedRealtime()); event.setStartTime(startTime); mAppOpsService.mHistoricalRegistry.incrementOpAccessedCount(parent.op, parent.uid, - parent.packageName, tag, event.getUidState(), event.getFlags(), startTime, - event.getAttributionFlags(), event.getAttributionChainId()); + parent.packageName, persistentDeviceId, tag, event.getUidState(), + event.getFlags(), startTime, event.getAttributionFlags(), + event.getAttributionChainId()); if (shouldSendActive) { mAppOpsService.scheduleOpActiveChangedIfNeededLocked(parent.op, parent.uid, parent.packageName, tag, event.getVirtualDeviceId(), true, diff --git a/services/core/java/com/android/server/appop/DiscreteRegistry.java b/services/core/java/com/android/server/appop/DiscreteRegistry.java index 5d83ad67d535..539dbca30d6b 100644 --- a/services/core/java/com/android/server/appop/DiscreteRegistry.java +++ b/services/core/java/com/android/server/appop/DiscreteRegistry.java @@ -41,6 +41,7 @@ import static android.app.AppOpsManager.OP_RECORD_AUDIO; import static android.app.AppOpsManager.OP_RESERVED_FOR_TESTING; import static android.app.AppOpsManager.flagsToString; import static android.app.AppOpsManager.getUidStateName; +import static android.companion.virtual.VirtualDeviceManager.PERSISTENT_DEVICE_ID_DEFAULT; import static java.lang.Long.min; import static java.lang.Math.max; @@ -52,6 +53,7 @@ import android.os.AsyncTask; import android.os.Build; import android.os.Environment; import android.os.FileUtils; +import android.permission.flags.Flags; import android.provider.DeviceConfig; import android.util.ArrayMap; import android.util.AtomicFile; @@ -76,7 +78,7 @@ import java.time.Instant; import java.time.temporal.ChronoUnit; import java.util.ArrayList; import java.util.Arrays; -import java.util.Collections; +import java.util.Comparator; import java.util.Date; import java.util.List; import java.util.Objects; @@ -164,6 +166,8 @@ final class DiscreteRegistry { private static final String TAG_OP = "o"; private static final String ATTR_OP_ID = "op"; + private static final String ATTR_DEVICE_ID = "di"; + private static final String TAG_TAG = "a"; private static final String ATTR_TAG = "at"; @@ -196,11 +200,14 @@ final class DiscreteRegistry { private boolean mDebugMode = false; DiscreteRegistry(Object inMemoryLock) { + this(inMemoryLock, new File(new File(Environment.getDataSystemDirectory(), "appops"), + "discrete")); + } + + DiscreteRegistry(Object inMemoryLock, File discreteAccessDir) { mInMemoryLock = inMemoryLock; synchronized (mOnDiskLock) { - mDiscreteAccessDir = new File( - new File(Environment.getDataSystemDirectory(), "appops"), - "discrete"); + mDiscreteAccessDir = discreteAccessDir; createDiscreteAccessDirLocked(); int largestChainId = readLargestChainIdFromDiskLocked(); synchronized (mInMemoryLock) { @@ -245,16 +252,24 @@ final class DiscreteRegistry { DEFAULT_DISCRETE_OPS); } - void recordDiscreteAccess(int uid, String packageName, int op, @Nullable String attributionTag, - @AppOpsManager.OpFlags int flags, @AppOpsManager.UidState int uidState, long accessTime, - long accessDuration, @AppOpsManager.AttributionFlags int attributionFlags, - int attributionChainId) { + void recordDiscreteAccess(int uid, String packageName, @NonNull String deviceId, int op, + @Nullable String attributionTag, @AppOpsManager.OpFlags int flags, + @AppOpsManager.UidState int uidState, long accessTime, long accessDuration, + @AppOpsManager.AttributionFlags int attributionFlags, int attributionChainId) { if (!isDiscreteOp(op, flags)) { return; } synchronized (mInMemoryLock) { - mDiscreteOps.addDiscreteAccess(op, uid, packageName, attributionTag, flags, uidState, - accessTime, accessDuration, attributionFlags, attributionChainId); + if (Flags.deviceAwareAppOpNewSchemaEnabled()) { + mDiscreteOps.addDiscreteAccess(op, uid, packageName, deviceId, attributionTag, + flags, uidState, accessTime, accessDuration, attributionFlags, + attributionChainId); + } else { + mDiscreteOps.addDiscreteAccess(op, uid, packageName, PERSISTENT_DEVICE_ID_DEFAULT, + attributionTag, flags, uidState, accessTime, accessDuration, + attributionFlags, attributionChainId); + } + } } @@ -294,7 +309,6 @@ final class DiscreteRegistry { discreteOps.filter(beginTimeMillis, endTimeMillis, filter, uidFilter, packageNameFilter, opNamesFilter, attributionTagFilter, flagsFilter, attributionChains); discreteOps.applyToHistoricalOps(result, attributionChains); - return; } private int readLargestChainIdFromDiskLocked() { @@ -355,28 +369,36 @@ final class DiscreteRegistry { String pkg = pkgs.keyAt(pkgNum); int nOps = ops.size(); for (int opNum = 0; opNum < nOps; opNum++) { - ArrayMap<String, List<DiscreteOpEvent>> attrOps = - ops.valueAt(opNum).mAttributedOps; int op = ops.keyAt(opNum); - int nAttrOps = attrOps.size(); - for (int attrOpNum = 0; attrOpNum < nAttrOps; attrOpNum++) { - List<DiscreteOpEvent> opEvents = attrOps.valueAt(attrOpNum); - String attributionTag = attrOps.keyAt(attrOpNum); - int nOpEvents = opEvents.size(); - for (int opEventNum = 0; opEventNum < nOpEvents; opEventNum++) { - DiscreteOpEvent event = opEvents.get(opEventNum); - if (event == null - || event.mAttributionChainId == ATTRIBUTION_CHAIN_ID_NONE - || (event.mAttributionFlags & ATTRIBUTION_FLAG_TRUSTED) == 0) { - continue; - } - - if (!chains.containsKey(event.mAttributionChainId)) { - chains.put(event.mAttributionChainId, - new AttributionChain(attributionExemptPkgs)); + ArrayMap<String, DiscreteDeviceOp> deviceOps = + ops.valueAt(opNum).mDeviceAttributedOps; + + int nDeviceOps = deviceOps.size(); + for (int deviceNum = 0; deviceNum < nDeviceOps; deviceNum++) { + ArrayMap<String, List<DiscreteOpEvent>> attrOps = + deviceOps.valueAt(deviceNum).mAttributedOps; + + int nAttrOps = attrOps.size(); + for (int attrOpNum = 0; attrOpNum < nAttrOps; attrOpNum++) { + List<DiscreteOpEvent> opEvents = attrOps.valueAt(attrOpNum); + String attributionTag = attrOps.keyAt(attrOpNum); + int nOpEvents = opEvents.size(); + for (int opEventNum = 0; opEventNum < nOpEvents; opEventNum++) { + DiscreteOpEvent event = opEvents.get(opEventNum); + if (event == null + || event.mAttributionChainId == ATTRIBUTION_CHAIN_ID_NONE + || (event.mAttributionFlags & ATTRIBUTION_FLAG_TRUSTED) + == 0) { + continue; + } + + if (!chains.containsKey(event.mAttributionChainId)) { + chains.put(event.mAttributionChainId, + new AttributionChain(attributionExemptPkgs)); + } + chains.get(event.mAttributionChainId) + .addEvent(pkg, uid, attributionTag, op, event); } - chains.get(event.mAttributionChainId) - .addEvent(pkg, uid, attributionTag, op, event); } } } @@ -464,7 +486,7 @@ final class DiscreteRegistry { createDiscreteAccessDir(); } - private DiscreteOps getAllDiscreteOps() { + DiscreteOps getAllDiscreteOps() { DiscreteOps discreteOps = new DiscreteOps(0); synchronized (mOnDiskLock) { @@ -608,7 +630,7 @@ final class DiscreteRegistry { } } - private final class DiscreteOps { + static final class DiscreteOps { ArrayMap<Integer, DiscreteUidOps> mUids; int mChainIdOffset; int mLargestChainId; @@ -634,8 +656,9 @@ final class DiscreteRegistry { } void addDiscreteAccess(int op, int uid, @NonNull String packageName, - @Nullable String attributionTag, @AppOpsManager.OpFlags int flags, - @AppOpsManager.UidState int uidState, long accessTime, long accessDuration, + @NonNull String deviceId, @Nullable String attributionTag, + @AppOpsManager.OpFlags int flags, @AppOpsManager.UidState int uidState, + long accessTime, long accessDuration, @AppOpsManager.AttributionFlags int attributionFlags, int attributionChainId) { int offsetChainId = attributionChainId; if (attributionChainId != ATTRIBUTION_CHAIN_ID_NONE) { @@ -649,8 +672,9 @@ final class DiscreteRegistry { mChainIdOffset = -1 * attributionChainId; } } - getOrCreateDiscreteUidOps(uid).addDiscreteAccess(op, packageName, attributionTag, flags, - uidState, accessTime, accessDuration, attributionFlags, offsetChainId); + getOrCreateDiscreteUidOps(uid).addDiscreteAccess(op, packageName, deviceId, + attributionTag, flags, uidState, accessTime, accessDuration, attributionFlags, + offsetChainId); } private void filter(long beginTimeMillis, long endTimeMillis, @@ -837,7 +861,7 @@ final class DiscreteRegistry { } } - private final class DiscreteUidOps { + static final class DiscreteUidOps { ArrayMap<String, DiscretePackageOps> mPackages; DiscreteUidOps() { @@ -889,12 +913,13 @@ final class DiscreteRegistry { mPackages.remove(packageName); } - void addDiscreteAccess(int op, @NonNull String packageName, @Nullable String attributionTag, - @AppOpsManager.OpFlags int flags, @AppOpsManager.UidState int uidState, - long accessTime, long accessDuration, + void addDiscreteAccess(int op, @NonNull String packageName, @NonNull String deviceId, + @Nullable String attributionTag, @AppOpsManager.OpFlags int flags, + @AppOpsManager.UidState int uidState, long accessTime, long accessDuration, @AppOpsManager.AttributionFlags int attributionFlags, int attributionChainId) { - getOrCreateDiscretePackageOps(packageName).addDiscreteAccess(op, attributionTag, flags, - uidState, accessTime, accessDuration, attributionFlags, attributionChainId); + getOrCreateDiscretePackageOps(packageName).addDiscreteAccess(op, deviceId, + attributionTag, flags, uidState, accessTime, accessDuration, + attributionFlags, attributionChainId); } private DiscretePackageOps getOrCreateDiscretePackageOps(String packageName) { @@ -948,7 +973,7 @@ final class DiscreteRegistry { } } - private final class DiscretePackageOps { + static final class DiscretePackageOps { ArrayMap<Integer, DiscreteOp> mPackageOps; DiscretePackageOps() { @@ -959,12 +984,12 @@ final class DiscreteRegistry { return mPackageOps.isEmpty(); } - void addDiscreteAccess(int op, @Nullable String attributionTag, + void addDiscreteAccess(int op, @NonNull String deviceId, @Nullable String attributionTag, @AppOpsManager.OpFlags int flags, @AppOpsManager.UidState int uidState, long accessTime, long accessDuration, @AppOpsManager.AttributionFlags int attributionFlags, int attributionChainId) { - getOrCreateDiscreteOp(op).addDiscreteAccess(attributionTag, flags, uidState, accessTime, - accessDuration, attributionFlags, attributionChainId); + getOrCreateDiscreteOp(op).addDiscreteAccess(deviceId, attributionTag, flags, uidState, + accessTime, accessDuration, attributionFlags, attributionChainId); } void merge(DiscretePackageOps other) { @@ -1056,10 +1081,148 @@ final class DiscreteRegistry { } } - private final class DiscreteOp { - ArrayMap<String, List<DiscreteOpEvent>> mAttributedOps; + static final class DiscreteOp { + ArrayMap<String, DiscreteDeviceOp> mDeviceAttributedOps; DiscreteOp() { + mDeviceAttributedOps = new ArrayMap<>(); + } + + boolean isEmpty() { + return mDeviceAttributedOps.isEmpty(); + } + + void merge(DiscreteOp other) { + int nDevices = other.mDeviceAttributedOps.size(); + for (int i = 0; i < nDevices; i++) { + String deviceId = other.mDeviceAttributedOps.keyAt(i); + DiscreteDeviceOp otherDeviceOps = other.mDeviceAttributedOps.valueAt(i); + getOrCreateDiscreteDeviceOp(deviceId).merge(otherDeviceOps); + } + } + + // Note: Update this method when we want to filter by device Id. + private void filter(long beginTimeMillis, long endTimeMillis, + @AppOpsManager.HistoricalOpsRequestFilter int filter, + @Nullable String attributionTagFilter, @AppOpsManager.OpFlags int flagsFilter, + int currentUid, String currentPkgName, int currentOp, + ArrayMap<Integer, AttributionChain> attributionChains) { + int nDevices = mDeviceAttributedOps.size(); + for (int i = nDevices - 1; i >= 0; i--) { + mDeviceAttributedOps.valueAt(i).filter(beginTimeMillis, endTimeMillis, filter, + attributionTagFilter, flagsFilter, currentUid, currentPkgName, currentOp, + attributionChains); + if (mDeviceAttributedOps.valueAt(i).isEmpty()) { + mDeviceAttributedOps.removeAt(i); + } + } + } + + private void offsetHistory(long offset) { + int nDevices = mDeviceAttributedOps.size(); + for (int i = 0; i < nDevices; i++) { + mDeviceAttributedOps.valueAt(i).offsetHistory(offset); + } + } + + void addDiscreteAccess(@NonNull String deviceId, @Nullable String attributionTag, + @AppOpsManager.OpFlags int flags, @AppOpsManager.UidState int uidState, + long accessTime, long accessDuration, + @AppOpsManager.AttributionFlags int attributionFlags, int attributionChainId) { + getOrCreateDiscreteDeviceOp(deviceId).addDiscreteAccess(attributionTag, flags, uidState, + accessTime, accessDuration, attributionFlags, attributionChainId); + } + + private DiscreteDeviceOp getOrCreateDiscreteDeviceOp(String deviceId) { + return mDeviceAttributedOps.computeIfAbsent(deviceId, k -> new DiscreteDeviceOp()); + } + + // TODO: b/308716962 Retrieve discrete histories from all devices and integrate them with + // HistoricalOps + private void applyToHistory(AppOpsManager.HistoricalOps result, int uid, + @NonNull String packageName, int op, + @NonNull ArrayMap<Integer, AttributionChain> attributionChains) { + if (mDeviceAttributedOps.get(PERSISTENT_DEVICE_ID_DEFAULT) != null) { + mDeviceAttributedOps.get(PERSISTENT_DEVICE_ID_DEFAULT).applyToHistory(result, uid, + packageName, op, attributionChains); + } + } + + private void dump(@NonNull PrintWriter pw, @NonNull SimpleDateFormat sdf, + @NonNull Date date, @NonNull String prefix, int nDiscreteOps) { + int nDevices = mDeviceAttributedOps.size(); + for (int i = 0; i < nDevices; i++) { + pw.print(prefix); + pw.print("Device: "); + pw.print(mDeviceAttributedOps.keyAt(i)); + pw.println(); + mDeviceAttributedOps.valueAt(i).dump(pw, sdf, date, prefix + " ", + nDiscreteOps); + } + } + + void serialize(TypedXmlSerializer out) throws Exception { + int nDevices = mDeviceAttributedOps.size(); + for (int i = 0; i < nDevices; i++) { + String deviceId = mDeviceAttributedOps.keyAt(i); + mDeviceAttributedOps.valueAt(i).serialize(out, deviceId); + } + } + + void deserialize(TypedXmlPullParser parser, long beginTimeMillis) throws Exception { + int outerDepth = parser.getDepth(); + while (XmlUtils.nextElementWithin(parser, outerDepth)) { + if (TAG_TAG.equals(parser.getName())) { + String attributionTag = parser.getAttributeValue(null, ATTR_TAG); + + int innerDepth = parser.getDepth(); + while (XmlUtils.nextElementWithin(parser, innerDepth)) { + if (TAG_ENTRY.equals(parser.getName())) { + long noteTime = parser.getAttributeLong(null, ATTR_NOTE_TIME); + long noteDuration = parser.getAttributeLong(null, ATTR_NOTE_DURATION, + -1); + int uidState = parser.getAttributeInt(null, ATTR_UID_STATE); + int opFlags = parser.getAttributeInt(null, ATTR_FLAGS); + int attributionFlags = parser.getAttributeInt(null, + ATTR_ATTRIBUTION_FLAGS, AppOpsManager.ATTRIBUTION_FLAGS_NONE); + int attributionChainId = parser.getAttributeInt(null, ATTR_CHAIN_ID, + AppOpsManager.ATTRIBUTION_CHAIN_ID_NONE); + String deviceId = parser.getAttributeValue(null, ATTR_DEVICE_ID); + if (deviceId == null) { + deviceId = PERSISTENT_DEVICE_ID_DEFAULT; + } + if (noteTime + noteDuration < beginTimeMillis) { + continue; + } + + DiscreteDeviceOp deviceOps = getOrCreateDiscreteDeviceOp(deviceId); + List<DiscreteOpEvent> events = + deviceOps.getOrCreateDiscreteOpEventsList(attributionTag); + DiscreteOpEvent event = new DiscreteOpEvent(noteTime, noteDuration, + uidState, opFlags, attributionFlags, attributionChainId); + events.add(event); + } + } + } + } + + int nDeviceOps = mDeviceAttributedOps.size(); + for (int i = 0; i < nDeviceOps; i++) { + DiscreteDeviceOp deviceOp = mDeviceAttributedOps.valueAt(i); + + int nAttrOps = deviceOp.mAttributedOps.size(); + for (int j = 0; j < nAttrOps; j++) { + List<DiscreteOpEvent> events = deviceOp.mAttributedOps.valueAt(j); + events.sort(Comparator.comparingLong(a -> a.mNoteTime)); + } + } + } + } + + static final class DiscreteDeviceOp { + ArrayMap<String, List<DiscreteOpEvent>> mAttributedOps; + + DiscreteDeviceOp() { mAttributedOps = new ArrayMap<>(); } @@ -1067,7 +1230,7 @@ final class DiscreteRegistry { return mAttributedOps.isEmpty(); } - void merge(DiscreteOp other) { + void merge(DiscreteDeviceOp other) { int nTags = other.mAttributedOps.size(); for (int i = 0; i < nTags; i++) { String tag = other.mAttributedOps.keyAt(i); @@ -1097,7 +1260,7 @@ final class DiscreteRegistry { currentUid, currentPkgName, currentOp, mAttributedOps.keyAt(i), attributionChains); mAttributedOps.put(tag, list); - if (list.size() == 0) { + if (list.isEmpty()) { mAttributedOps.removeAt(i); } } @@ -1125,8 +1288,7 @@ final class DiscreteRegistry { List<DiscreteOpEvent> attributedOps = getOrCreateDiscreteOpEventsList( attributionTag); - int nAttributedOps = attributedOps.size(); - int i = nAttributedOps; + int i = attributedOps.size(); for (; i > 0; i--) { DiscreteOpEvent previousOp = attributedOps.get(i - 1); if (discretizeTimeStamp(previousOp.mNoteTime) < discretizeTimeStamp(accessTime)) { @@ -1148,12 +1310,8 @@ final class DiscreteRegistry { } private List<DiscreteOpEvent> getOrCreateDiscreteOpEventsList(String attributionTag) { - List<DiscreteOpEvent> result = mAttributedOps.get(attributionTag); - if (result == null) { - result = new ArrayList<>(); - mAttributedOps.put(attributionTag, result); - } - return result; + return mAttributedOps.computeIfAbsent(attributionTag, + k -> new ArrayList<>()); } private void applyToHistory(AppOpsManager.HistoricalOps result, int uid, @@ -1167,8 +1325,7 @@ final class DiscreteRegistry { for (int j = 0; j < nEvents; j++) { DiscreteOpEvent event = events.get(j); AppOpsManager.OpEventProxyInfo proxy = null; - if (event.mAttributionChainId != ATTRIBUTION_CHAIN_ID_NONE - && attributionChains != null) { + if (event.mAttributionChainId != ATTRIBUTION_CHAIN_ID_NONE) { AttributionChain chain = attributionChains.get(event.mAttributionChainId); if (chain != null && chain.isComplete() && chain.isStart(packageName, uid, tag, op, event) @@ -1198,65 +1355,31 @@ final class DiscreteRegistry { int first = nDiscreteOps < 1 ? 0 : max(0, nOps - nDiscreteOps); for (int j = first; j < nOps; j++) { ops.get(j).dump(pw, sdf, date, prefix + " "); - } } } - void serialize(TypedXmlSerializer out) throws Exception { + void serialize(TypedXmlSerializer out, String deviceId) throws Exception { int nAttributions = mAttributedOps.size(); for (int i = 0; i < nAttributions; i++) { out.startTag(null, TAG_TAG); String tag = mAttributedOps.keyAt(i); if (tag != null) { - out.attribute(null, ATTR_TAG, mAttributedOps.keyAt(i)); + out.attribute(null, ATTR_TAG, tag); } List<DiscreteOpEvent> ops = mAttributedOps.valueAt(i); int nOps = ops.size(); for (int j = 0; j < nOps; j++) { out.startTag(null, TAG_ENTRY); - ops.get(j).serialize(out); + ops.get(j).serialize(out, deviceId); out.endTag(null, TAG_ENTRY); } out.endTag(null, TAG_TAG); } } - - void deserialize(TypedXmlPullParser parser, long beginTimeMillis) throws Exception { - int outerDepth = parser.getDepth(); - while (XmlUtils.nextElementWithin(parser, outerDepth)) { - if (TAG_TAG.equals(parser.getName())) { - String attributionTag = parser.getAttributeValue(null, ATTR_TAG); - List<DiscreteOpEvent> events = getOrCreateDiscreteOpEventsList( - attributionTag); - int innerDepth = parser.getDepth(); - while (XmlUtils.nextElementWithin(parser, innerDepth)) { - if (TAG_ENTRY.equals(parser.getName())) { - long noteTime = parser.getAttributeLong(null, ATTR_NOTE_TIME); - long noteDuration = parser.getAttributeLong(null, ATTR_NOTE_DURATION, - -1); - int uidState = parser.getAttributeInt(null, ATTR_UID_STATE); - int opFlags = parser.getAttributeInt(null, ATTR_FLAGS); - int attributionFlags = parser.getAttributeInt(null, - ATTR_ATTRIBUTION_FLAGS, AppOpsManager.ATTRIBUTION_FLAGS_NONE); - int attributionChainId = parser.getAttributeInt(null, ATTR_CHAIN_ID, - AppOpsManager.ATTRIBUTION_CHAIN_ID_NONE); - if (noteTime + noteDuration < beginTimeMillis) { - continue; - } - DiscreteOpEvent event = new DiscreteOpEvent(noteTime, noteDuration, - uidState, opFlags, attributionFlags, attributionChainId); - events.add(event); - } - } - Collections.sort(events, (a, b) -> a.mNoteTime < b.mNoteTime ? -1 - : (a.mNoteTime == b.mNoteTime ? 0 : 1)); - } - } - } } - private final class DiscreteOpEvent { + static final class DiscreteOpEvent { final long mNoteTime; final long mNoteDuration; final @AppOpsManager.UidState int mUidState; @@ -1306,7 +1429,7 @@ final class DiscreteRegistry { pw.println(); } - private void serialize(TypedXmlSerializer out) throws Exception { + private void serialize(TypedXmlSerializer out, String deviceId) throws Exception { out.attributeLong(null, ATTR_NOTE_TIME, mNoteTime); if (mNoteDuration != -1) { out.attributeLong(null, ATTR_NOTE_DURATION, mNoteDuration); @@ -1317,6 +1440,9 @@ final class DiscreteRegistry { if (mAttributionChainId != AppOpsManager.ATTRIBUTION_CHAIN_ID_NONE) { out.attributeInt(null, ATTR_CHAIN_ID, mAttributionChainId); } + if (!Objects.equals(deviceId, PERSISTENT_DEVICE_ID_DEFAULT)) { + out.attribute(null, ATTR_DEVICE_ID, deviceId); + } out.attributeInt(null, ATTR_UID_STATE, mUidState); out.attributeInt(null, ATTR_FLAGS, mOpFlag); } diff --git a/services/core/java/com/android/server/appop/HistoricalRegistry.java b/services/core/java/com/android/server/appop/HistoricalRegistry.java index dbd47d00718f..fffb1082acb1 100644 --- a/services/core/java/com/android/server/appop/HistoricalRegistry.java +++ b/services/core/java/com/android/server/appop/HistoricalRegistry.java @@ -472,9 +472,9 @@ final class HistoricalRegistry { } void incrementOpAccessedCount(int op, int uid, @NonNull String packageName, - @Nullable String attributionTag, @UidState int uidState, @OpFlags int flags, - long accessTime, @AppOpsManager.AttributionFlags int attributionFlags, - int attributionChainId) { + @NonNull String deviceId, @Nullable String attributionTag, @UidState int uidState, + @OpFlags int flags, long accessTime, + @AppOpsManager.AttributionFlags int attributionFlags, int attributionChainId) { synchronized (mInMemoryLock) { if (mMode == AppOpsManager.HISTORICAL_MODE_ENABLED_ACTIVE) { if (!isPersistenceInitializedMLocked()) { @@ -485,8 +485,9 @@ final class HistoricalRegistry { System.currentTimeMillis()).increaseAccessCount(op, uid, packageName, attributionTag, uidState, flags, 1); - mDiscreteRegistry.recordDiscreteAccess(uid, packageName, op, attributionTag, - flags, uidState, accessTime, -1, attributionFlags, attributionChainId); + mDiscreteRegistry.recordDiscreteAccess(uid, packageName, deviceId, op, + attributionTag, flags, uidState, accessTime, -1, attributionFlags, + attributionChainId); } } } @@ -507,8 +508,8 @@ final class HistoricalRegistry { } void increaseOpAccessDuration(int op, int uid, @NonNull String packageName, - @Nullable String attributionTag, @UidState int uidState, @OpFlags int flags, - long eventStartTime, long increment, + @NonNull String deviceId, @Nullable String attributionTag, @UidState int uidState, + @OpFlags int flags, long eventStartTime, long increment, @AppOpsManager.AttributionFlags int attributionFlags, int attributionChainId) { synchronized (mInMemoryLock) { if (mMode == AppOpsManager.HISTORICAL_MODE_ENABLED_ACTIVE) { @@ -519,9 +520,9 @@ final class HistoricalRegistry { getUpdatedPendingHistoricalOpsMLocked( System.currentTimeMillis()).increaseAccessDuration(op, uid, packageName, attributionTag, uidState, flags, increment); - mDiscreteRegistry.recordDiscreteAccess(uid, packageName, op, attributionTag, - flags, uidState, eventStartTime, increment, attributionFlags, - attributionChainId); + mDiscreteRegistry.recordDiscreteAccess(uid, packageName, deviceId, op, + attributionTag, flags, uidState, eventStartTime, increment, + attributionFlags, attributionChainId); } } } diff --git a/services/core/java/com/android/server/audio/AudioDeviceBroker.java b/services/core/java/com/android/server/audio/AudioDeviceBroker.java index 92553b9705b7..ca907c57a858 100644 --- a/services/core/java/com/android/server/audio/AudioDeviceBroker.java +++ b/services/core/java/com/android/server/audio/AudioDeviceBroker.java @@ -2799,6 +2799,10 @@ public class AudioDeviceBroker { return; } final SettingsAdapter settingsAdapter = mAudioService.getSettings(); + if (settingsAdapter == null) { + Log.e(TAG, "No settings adapter when saving AdiDeviceState: " + deviceSettings); + return; + } try { boolean res = settingsAdapter.putSecureStringForUser(mAudioService.getContentResolver(), Settings.Secure.AUDIO_DEVICE_INVENTORY, @@ -2814,6 +2818,12 @@ public class AudioDeviceBroker { private String readDeviceSettings() { final SettingsAdapter settingsAdapter = mAudioService.getSettings(); final ContentResolver contentResolver = mAudioService.getContentResolver(); + if (settingsAdapter == null || contentResolver == null) { + // should not happen, throw Exception for stack trace + Log.e(TAG, "No settings adapter or content resolver to read device settings", + new Exception("readDeviceSettings_NPE")); + return ""; + } return settingsAdapter.getSecureStringForUser(contentResolver, Settings.Secure.AUDIO_DEVICE_INVENTORY, UserHandle.USER_CURRENT); } diff --git a/services/core/java/com/android/server/audio/AudioDeviceInventory.java b/services/core/java/com/android/server/audio/AudioDeviceInventory.java index ca69f31adb35..8d8a54ea426d 100644 --- a/services/core/java/com/android/server/audio/AudioDeviceInventory.java +++ b/services/core/java/com/android/server/audio/AudioDeviceInventory.java @@ -31,6 +31,7 @@ import static android.media.AudioSystem.isBluetoothScoOutDevice; import static android.media.audio.Flags.automaticBtDeviceType; import static com.android.internal.annotations.VisibleForTesting.Visibility.PACKAGE; +import static com.android.media.audio.Flags.asDeviceConnectionFailure; import android.annotation.NonNull; import android.annotation.Nullable; @@ -529,6 +530,17 @@ public class AudioDeviceInventory { } }; + /** + * package-protected for unit testing only + * Returns the currently connected devices + * @return the collection of connected devices + */ + /*package*/ @NonNull Collection<DeviceInfo> getConnectedDevices() { + synchronized (mDevicesLock) { + return mConnectedDevices.values(); + } + } + // List of devices actually connected to AudioPolicy (through AudioSystem), only one // by device type, which is used as the key, value is the DeviceInfo generated key. // For the moment only for A2DP sink devices. @@ -598,8 +610,9 @@ public class AudioDeviceInventory { /** * Class to store info about connected devices. * Use makeDeviceListKey() to make a unique key for this list. + * Package-protected for unit tests */ - private static class DeviceInfo { + /*package*/ static class DeviceInfo { final int mDeviceType; final @NonNull String mDeviceName; final @NonNull String mDeviceAddress; @@ -762,13 +775,27 @@ public class AudioDeviceInventory { // Always executed on AudioDeviceBroker message queue /*package*/ void onRestoreDevices() { synchronized (mDevicesLock) { + int res; + List<DeviceInfo> failedReconnectionDeviceList = new ArrayList<>(/*initialCapacity*/ 0); //TODO iterate on mApmConnectedDevices instead once it handles all device types for (DeviceInfo di : mConnectedDevices.values()) { - mAudioSystem.setDeviceConnectionState(new AudioDeviceAttributes(di.mDeviceType, + res = mAudioSystem.setDeviceConnectionState(new AudioDeviceAttributes( + di.mDeviceType, di.mDeviceAddress, di.mDeviceName), AudioSystem.DEVICE_STATE_AVAILABLE, di.mDeviceCodecFormat); + if (asDeviceConnectionFailure() && res != AudioSystem.AUDIO_STATUS_OK) { + failedReconnectionDeviceList.add(di); + } + } + if (asDeviceConnectionFailure()) { + for (DeviceInfo di : failedReconnectionDeviceList) { + AudioService.sDeviceLogger.enqueueAndSlog( + "Device inventory restore failed to reconnect " + di, + EventLogger.Event.ALOGE, TAG); + mConnectedDevices.remove(di.getKey(), di); + } } mAppliedStrategyRolesInt.clear(); mAppliedPresetRolesInt.clear(); @@ -2070,8 +2097,9 @@ public class AudioDeviceInventory { "APM failed to make available A2DP device addr=" + Utils.anonymizeBluetoothAddress(address) + " error=" + res).printSlog(EventLogger.Event.ALOGE, TAG)); - // TODO: connection failed, stop here - // TODO: return; + if (asDeviceConnectionFailure()) { + return; + } } else { AudioService.sDeviceLogger.enqueue(new EventLogger.StringEvent( "A2DP sink device addr=" + Utils.anonymizeBluetoothAddress(address) @@ -2336,8 +2364,7 @@ public class AudioDeviceInventory { "APM failed to make unavailable A2DP device addr=" + Utils.anonymizeBluetoothAddress(address) + " error=" + res).printSlog(EventLogger.Event.ALOGE, TAG)); - // TODO: failed to disconnect, stop here - // TODO: return; + // not taking further action: proceeding as if disconnection from APM worked } else { AudioService.sDeviceLogger.enqueue((new EventLogger.StringEvent( "A2DP device addr=" + Utils.anonymizeBluetoothAddress(address) @@ -2383,8 +2410,9 @@ public class AudioDeviceInventory { "APM failed to make available A2DP source device addr=" + Utils.anonymizeBluetoothAddress(address) + " error=" + res).printSlog(EventLogger.Event.ALOGE, TAG)); - // TODO: connection failed, stop here - // TODO: return + if (asDeviceConnectionFailure()) { + return; + } } else { AudioService.sDeviceLogger.enqueue(new EventLogger.StringEvent( "A2DP source device addr=" + Utils.anonymizeBluetoothAddress(address) @@ -2402,6 +2430,7 @@ public class AudioDeviceInventory { mAudioSystem.setDeviceConnectionState(ada, AudioSystem.DEVICE_STATE_UNAVAILABLE, AudioSystem.AUDIO_FORMAT_DEFAULT); + // always remove regardless of the result mConnectedDevices.remove( DeviceInfo.makeDeviceListKey(AudioSystem.DEVICE_IN_BLUETOOTH_A2DP, address)); mDeviceBroker.postCheckCommunicationDeviceRemoval(ada); @@ -2418,9 +2447,18 @@ public class AudioDeviceInventory { AudioDeviceAttributes ada = new AudioDeviceAttributes( DEVICE_OUT_HEARING_AID, address, name); - mAudioSystem.setDeviceConnectionState(ada, + final int res = mAudioSystem.setDeviceConnectionState(ada, AudioSystem.DEVICE_STATE_AVAILABLE, AudioSystem.AUDIO_FORMAT_DEFAULT); + if (asDeviceConnectionFailure() && res != AudioSystem.AUDIO_STATUS_OK) { + AudioService.sDeviceLogger.enqueueAndSlog( + "APM failed to make available HearingAid addr=" + address + + " error=" + res, + EventLogger.Event.ALOGE, TAG); + return; + } + AudioService.sDeviceLogger.enqueueAndSlog("HearingAid made available addr=" + address, + EventLogger.Event.ALOGI, TAG); mConnectedDevices.put( DeviceInfo.makeDeviceListKey(DEVICE_OUT_HEARING_AID, address), new DeviceInfo(DEVICE_OUT_HEARING_AID, name, address)); @@ -2447,6 +2485,7 @@ public class AudioDeviceInventory { mAudioSystem.setDeviceConnectionState(ada, AudioSystem.DEVICE_STATE_UNAVAILABLE, AudioSystem.AUDIO_FORMAT_DEFAULT); + // always remove regardless of return code mConnectedDevices.remove( DeviceInfo.makeDeviceListKey(DEVICE_OUT_HEARING_AID, address)); // Remove Hearing Aid routes as well @@ -2540,11 +2579,12 @@ public class AudioDeviceInventory { final int res = mAudioSystem.setDeviceConnectionState(ada, AudioSystem.DEVICE_STATE_AVAILABLE, codec); if (res != AudioSystem.AUDIO_STATUS_OK) { - AudioService.sDeviceLogger.enqueue(new EventLogger.StringEvent( + AudioService.sDeviceLogger.enqueueAndSlog( "APM failed to make available LE Audio device addr=" + address - + " error=" + res).printSlog(EventLogger.Event.ALOGE, TAG)); - // TODO: connection failed, stop here - // TODO: return; + + " error=" + res, EventLogger.Event.ALOGE, TAG); + if (asDeviceConnectionFailure()) { + return; + } } else { AudioService.sDeviceLogger.enqueue(new EventLogger.StringEvent( "LE Audio " + (AudioSystem.isInputDevice(device) ? "source" : "sink") @@ -2596,8 +2636,7 @@ public class AudioDeviceInventory { AudioService.sDeviceLogger.enqueue(new EventLogger.StringEvent( "APM failed to make unavailable LE Audio device addr=" + address + " error=" + res).printSlog(EventLogger.Event.ALOGE, TAG)); - // TODO: failed to disconnect, stop here - // TODO: return; + // not taking further action: proceeding as if disconnection from APM worked } else { AudioService.sDeviceLogger.enqueue(new EventLogger.StringEvent( "LE Audio device addr=" + Utils.anonymizeBluetoothAddress(address) diff --git a/services/core/java/com/android/server/audio/AudioService.java b/services/core/java/com/android/server/audio/AudioService.java index 1183768a272b..ac43e86a07c4 100644 --- a/services/core/java/com/android/server/audio/AudioService.java +++ b/services/core/java/com/android/server/audio/AudioService.java @@ -63,6 +63,7 @@ import static android.provider.Settings.Secure.VOLUME_HUSH_VIBRATE; import static com.android.internal.annotations.VisibleForTesting.Visibility.PACKAGE; import static com.android.media.audio.Flags.absVolumeIndexFix; import static com.android.media.audio.Flags.alarmMinVolumeZero; +import static com.android.media.audio.Flags.asDeviceConnectionFailure; import static com.android.media.audio.Flags.audioserverPermissions; import static com.android.media.audio.Flags.disablePrescaleAbsoluteVolume; import static com.android.media.audio.Flags.replaceStreamBtSco; @@ -4306,7 +4307,8 @@ public class AudioService extends IAudioService.Stub super.getVolumeGroupVolumeIndex_enforcePermission(); synchronized (VolumeStreamState.class) { if (sVolumeGroupStates.indexOfKey(groupId) < 0) { - throw new IllegalArgumentException("No volume group for id " + groupId); + Log.e(TAG, "No volume group for id " + groupId); + return 0; } VolumeGroupState vgs = sVolumeGroupStates.get(groupId); // Return 0 when muted, not min index since for e.g. Voice Call, it has a non zero @@ -4322,7 +4324,8 @@ public class AudioService extends IAudioService.Stub super.getVolumeGroupMaxVolumeIndex_enforcePermission(); synchronized (VolumeStreamState.class) { if (sVolumeGroupStates.indexOfKey(groupId) < 0) { - throw new IllegalArgumentException("No volume group for id " + groupId); + Log.e(TAG, "No volume group for id " + groupId); + return 0; } VolumeGroupState vgs = sVolumeGroupStates.get(groupId); return vgs.getMaxIndex(); @@ -4336,7 +4339,8 @@ public class AudioService extends IAudioService.Stub super.getVolumeGroupMinVolumeIndex_enforcePermission(); synchronized (VolumeStreamState.class) { if (sVolumeGroupStates.indexOfKey(groupId) < 0) { - throw new IllegalArgumentException("No volume group for id " + groupId); + Log.e(TAG, "No volume group for id " + groupId); + return 0; } VolumeGroupState vgs = sVolumeGroupStates.get(groupId); return vgs.getMinIndex(); @@ -4765,6 +4769,8 @@ public class AudioService extends IAudioService.Stub private void dumpFlags(PrintWriter pw) { pw.println("\nFun with Flags:"); + pw.println("\tcom.android.media.audio.as_device_connection_failure:" + + asDeviceConnectionFailure()); pw.println("\tandroid.media.audio.autoPublicVolumeApiHardening:" + autoPublicVolumeApiHardening()); pw.println("\tandroid.media.audio.Flags.automaticBtDeviceType:" @@ -8259,11 +8265,21 @@ public class AudioService extends IAudioService.Stub private static final SparseArray<VolumeGroupState> sVolumeGroupStates = new SparseArray<>(); private void initVolumeGroupStates() { + int btScoGroupId = -1; + VolumeGroupState voiceCallGroup = null; for (final AudioVolumeGroup avg : getAudioVolumeGroups()) { try { - // if no valid attributes, this volume group is not controllable - if (ensureValidAttributes(avg)) { - sVolumeGroupStates.append(avg.getId(), new VolumeGroupState(avg)); + if (ensureValidVolumeGroup(avg)) { + final VolumeGroupState vgs = new VolumeGroupState(avg); + sVolumeGroupStates.append(avg.getId(), vgs); + if (vgs.isVoiceCall()) { + voiceCallGroup = vgs; + } + } else { + // invalid volume group will be reported for bt sco group with no other + // legacy stream type, we try to replace it in sVolumeGroupStates with the + // voice call volume group + btScoGroupId = avg.getId(); } } catch (IllegalArgumentException e) { // Volume Groups without attributes are not controllable through set/get volume @@ -8271,10 +8287,15 @@ public class AudioService extends IAudioService.Stub if (DEBUG_VOL) { Log.d(TAG, "volume group " + avg.name() + " for internal policy needs"); } - continue; } } + if (replaceStreamBtSco() && btScoGroupId >= 0 && voiceCallGroup != null) { + // the bt sco group is deprecated, storing the voice call group instead + // to keep the code backwards compatible when calling the volume group APIs + sVolumeGroupStates.append(btScoGroupId, voiceCallGroup); + } + // need mSettingsLock for vgs.applyAllVolumes -> vss.setIndex which grabs this lock after // VSS.class. Locking order needs to be preserved synchronized (mSettingsLock) { @@ -8285,7 +8306,15 @@ public class AudioService extends IAudioService.Stub } } - private boolean ensureValidAttributes(AudioVolumeGroup avg) { + /** + * Returns false if the legacy stream types only contains the deprecated + * {@link AudioSystem#STREAM_BLUETOOTH_SCO}. + * + * @throws IllegalArgumentException if it has more than one non-default {@link AudioAttributes} + * + * @param avg the volume group to check + */ + private boolean ensureValidVolumeGroup(AudioVolumeGroup avg) { boolean hasAtLeastOneValidAudioAttributes = avg.getAudioAttributes().stream() .anyMatch(aa -> !aa.equals(AudioProductStrategy.getDefaultAttributes())); if (!hasAtLeastOneValidAudioAttributes) { @@ -8293,10 +8322,11 @@ public class AudioService extends IAudioService.Stub + " has no valid audio attributes"); } if (replaceStreamBtSco()) { - for (int streamType : avg.getLegacyStreamTypes()) { - if (streamType == AudioSystem.STREAM_BLUETOOTH_SCO) { - return false; - } + // if there are multiple legacy stream types associated we can omit stream bt sco + // otherwise this is not a valid volume group + if (avg.getLegacyStreamTypes().length == 1 + && avg.getLegacyStreamTypes()[0] == AudioSystem.STREAM_BLUETOOTH_SCO) { + return false; } } return true; @@ -8637,6 +8667,10 @@ public class AudioService extends IAudioService.Stub return mHasValidStreamType && mPublicStreamType == AudioSystem.STREAM_MUSIC; } + public boolean isVoiceCall() { + return mHasValidStreamType && mPublicStreamType == AudioSystem.STREAM_VOICE_CALL; + } + public void applyAllVolumes(boolean userSwitch) { String caller = "from vgs"; synchronized (AudioService.VolumeStreamState.class) { diff --git a/services/core/java/com/android/server/biometrics/biometrics.aconfig b/services/core/java/com/android/server/biometrics/biometrics.aconfig index 92fd9cbcf14e..15c88500210e 100644 --- a/services/core/java/com/android/server/biometrics/biometrics.aconfig +++ b/services/core/java/com/android/server/biometrics/biometrics.aconfig @@ -14,3 +14,10 @@ flag { description: "This flag controls whether virtual HAL is used for testing instead of TestHal " bug: "294254230" } + +flag { + name: "notify_fingerprint_loe" + namespace: "biometrics_framework" + description: "This flag controls whether a notification should be sent to notify user when loss of enrollment happens" + bug: "351036558" +} diff --git a/services/core/java/com/android/server/biometrics/sensors/BiometricNotificationUtils.java b/services/core/java/com/android/server/biometrics/sensors/BiometricNotificationUtils.java index 53e6bdb2ab5f..27f9cc88e28f 100644 --- a/services/core/java/com/android/server/biometrics/sensors/BiometricNotificationUtils.java +++ b/services/core/java/com/android/server/biometrics/sensors/BiometricNotificationUtils.java @@ -151,6 +151,43 @@ public class BiometricNotificationUtils { } /** + * Shows a fingerprint notification for loss of enrollment + */ + public static void showFingerprintLoeNotification(@NonNull Context context) { + Slog.d(TAG, "Showing fingerprint LOE notification"); + + final String name = + context.getString(R.string.device_unlock_notification_name); + final String title = context.getString(R.string.fingerprint_dangling_notification_title); + final String content = context.getString(R.string.fingerprint_loe_notification_msg); + + // Create "Set up" notification action button. + final Intent setupIntent = + new Intent(BiometricDanglingReceiver.ACTION_FINGERPRINT_RE_ENROLL_LAUNCH); + final PendingIntent setupPendingIntent = PendingIntent.getBroadcastAsUser(context, 0, + setupIntent, PendingIntent.FLAG_IMMUTABLE, UserHandle.CURRENT); + final String setupText = + context.getString(R.string.biometric_dangling_notification_action_set_up); + final Notification.Action setupAction = new Notification.Action.Builder( + null, setupText, setupPendingIntent).build(); + + // Create "Not now" notification action button. + final Intent notNowIntent = + new Intent(BiometricDanglingReceiver.ACTION_FINGERPRINT_RE_ENROLL_DISMISS); + final PendingIntent notNowPendingIntent = PendingIntent.getBroadcastAsUser(context, 0, + notNowIntent, PendingIntent.FLAG_IMMUTABLE, UserHandle.CURRENT); + final String notNowText = context.getString( + R.string.biometric_dangling_notification_action_not_now); + final Notification.Action notNowAction = new Notification.Action.Builder( + null, notNowText, notNowPendingIntent).build(); + + showNotificationHelper(context, name, title, content, setupPendingIntent, setupAction, + notNowAction, Notification.CATEGORY_SYSTEM, FINGERPRINT_RE_ENROLL_CHANNEL, + FINGERPRINT_RE_ENROLL_NOTIFICATION_TAG, Notification.VISIBILITY_SECRET, false, + Notification.FLAG_NO_CLEAR); + } + + /** * Shows a fingerprint bad calibration notification. */ public static void showBadCalibrationNotification(@NonNull Context context) { diff --git a/services/core/java/com/android/server/biometrics/sensors/BiometricUserState.java b/services/core/java/com/android/server/biometrics/sensors/BiometricUserState.java index 7fb27b6896da..63678aaa16c3 100644 --- a/services/core/java/com/android/server/biometrics/sensors/BiometricUserState.java +++ b/services/core/java/com/android/server/biometrics/sensors/BiometricUserState.java @@ -57,6 +57,7 @@ public abstract class BiometricUserState<T extends BiometricAuthenticator.Identi protected boolean mInvalidationInProgress; protected final Context mContext; protected final File mFile; + private boolean mIsInvalidBiometricState = false; private final Runnable mWriteStateRunnable = this::doWriteStateInternal; @@ -102,7 +103,7 @@ public abstract class BiometricUserState<T extends BiometricAuthenticator.Identi serializer.endDocument(); destination.finishWrite(out); } catch (Throwable t) { - Slog.wtf(TAG, "Failed to write settings, restoring backup", t); + Slog.e(TAG, "Failed to write settings, restoring backup", t); destination.failWrite(out); throw new IllegalStateException("Failed to write to file: " + mFile.toString(), t); } finally { @@ -192,6 +193,29 @@ public abstract class BiometricUserState<T extends BiometricAuthenticator.Identi } } + /** + * Return true if the biometric file is correctly read. Otherwise return false. + */ + public boolean isInvalidBiometricState() { + return mIsInvalidBiometricState; + } + + /** + * Delete the file of the biometric state. + */ + public void deleteBiometricFile() { + synchronized (this) { + if (!mFile.exists()) { + return; + } + if (mFile.delete()) { + Slog.i(TAG, mFile + " is deleted successfully"); + } else { + Slog.i(TAG, "Failed to delete " + mFile); + } + } + } + private boolean isUnique(String name) { for (T identifier : mBiometrics) { if (identifier.getName().equals(name)) { @@ -218,7 +242,8 @@ public abstract class BiometricUserState<T extends BiometricAuthenticator.Identi try { in = new FileInputStream(mFile); } catch (FileNotFoundException fnfe) { - Slog.i(TAG, "No fingerprint state"); + Slog.i(TAG, "No fingerprint state", fnfe); + mIsInvalidBiometricState = true; return; } try { diff --git a/services/core/java/com/android/server/biometrics/sensors/BiometricUtils.java b/services/core/java/com/android/server/biometrics/sensors/BiometricUtils.java index ebe467942790..0b4f64042055 100644 --- a/services/core/java/com/android/server/biometrics/sensors/BiometricUtils.java +++ b/services/core/java/com/android/server/biometrics/sensors/BiometricUtils.java @@ -33,4 +33,14 @@ public interface BiometricUtils<T extends BiometricAuthenticator.Identifier> { CharSequence getUniqueName(Context context, int userId); void setInvalidationInProgress(Context context, int userId, boolean inProgress); boolean isInvalidationInProgress(Context context, int userId); + + /** + * Return true if the biometric file is correctly read. Otherwise return false. + */ + boolean hasValidBiometricUserState(Context context, int userId); + + /** + * Delete the file of the biometric state. + */ + void deleteStateForUser(int userId); }
\ No newline at end of file diff --git a/services/core/java/com/android/server/biometrics/sensors/InternalCleanupClient.java b/services/core/java/com/android/server/biometrics/sensors/InternalCleanupClient.java index 69ad1523118d..3b6aeef92421 100644 --- a/services/core/java/com/android/server/biometrics/sensors/InternalCleanupClient.java +++ b/services/core/java/com/android/server/biometrics/sensors/InternalCleanupClient.java @@ -25,6 +25,7 @@ import android.util.Slog; import com.android.internal.annotations.VisibleForTesting; import com.android.server.biometrics.BiometricsProto; +import com.android.server.biometrics.Flags; import com.android.server.biometrics.log.BiometricContext; import com.android.server.biometrics.log.BiometricLogger; @@ -62,7 +63,7 @@ public abstract class InternalCleanupClient<S extends BiometricAuthenticator.Ide } private final ArrayList<UserTemplate> mUnknownHALTemplates = new ArrayList<>(); - private final BiometricUtils<S> mBiometricUtils; + protected final BiometricUtils<S> mBiometricUtils; private final Map<Integer, Long> mAuthenticatorIds; private final boolean mHasEnrollmentsBeforeStarting; private BaseClientMonitor mCurrentTask; @@ -105,6 +106,11 @@ public abstract class InternalCleanupClient<S extends BiometricAuthenticator.Ide startCleanupUnknownHalTemplates(); } } + + if (mBiometricUtils.hasValidBiometricUserState(getContext(), getTargetUserId()) + && Flags.notifyFingerprintLoe()) { + handleInvalidBiometricState(); + } } }; @@ -248,4 +254,8 @@ public abstract class InternalCleanupClient<S extends BiometricAuthenticator.Ide public ArrayList<UserTemplate> getUnknownHALTemplates() { return mUnknownHALTemplates; } + + protected void handleInvalidBiometricState() {} + + protected abstract int getModality(); } diff --git a/services/core/java/com/android/server/biometrics/sensors/face/FaceUtils.java b/services/core/java/com/android/server/biometrics/sensors/face/FaceUtils.java index c5744780cd71..79285cbd9ea5 100644 --- a/services/core/java/com/android/server/biometrics/sensors/face/FaceUtils.java +++ b/services/core/java/com/android/server/biometrics/sensors/face/FaceUtils.java @@ -124,6 +124,22 @@ public class FaceUtils implements BiometricUtils<Face> { return getStateForUser(context, userId).isInvalidationInProgress(); } + @Override + public boolean hasValidBiometricUserState(Context context, int userId) { + return getStateForUser(context, userId).isInvalidBiometricState(); + } + + @Override + public void deleteStateForUser(int userId) { + synchronized (this) { + FaceUserState state = mUserStates.get(userId); + if (state != null) { + state.deleteBiometricFile(); + mUserStates.delete(userId); + } + } + } + private FaceUserState getStateForUser(Context ctx, int userId) { synchronized (this) { FaceUserState state = mUserStates.get(userId); diff --git a/services/core/java/com/android/server/biometrics/sensors/face/aidl/FaceInternalCleanupClient.java b/services/core/java/com/android/server/biometrics/sensors/face/aidl/FaceInternalCleanupClient.java index e75c6aba1489..964bf6cad63c 100644 --- a/services/core/java/com/android/server/biometrics/sensors/face/aidl/FaceInternalCleanupClient.java +++ b/services/core/java/com/android/server/biometrics/sensors/face/aidl/FaceInternalCleanupClient.java @@ -19,6 +19,7 @@ package com.android.server.biometrics.sensors.face.aidl; import android.annotation.NonNull; import android.content.Context; import android.hardware.biometrics.BiometricAuthenticator; +import android.hardware.biometrics.BiometricsProtoEnums; import android.hardware.biometrics.face.IFace; import android.hardware.face.Face; import android.os.IBinder; @@ -77,4 +78,9 @@ public class FaceInternalCleanupClient extends InternalCleanupClient<Face, AidlS FaceUtils.getInstance(getSensorId()).addBiometricForUser( getContext(), getTargetUserId(), (Face) identifier); } + + @Override + protected int getModality() { + return BiometricsProtoEnums.MODALITY_FACE; + } } diff --git a/services/core/java/com/android/server/biometrics/sensors/fingerprint/FingerprintUtils.java b/services/core/java/com/android/server/biometrics/sensors/fingerprint/FingerprintUtils.java index 0062d31962a9..b8c06c730edc 100644 --- a/services/core/java/com/android/server/biometrics/sensors/fingerprint/FingerprintUtils.java +++ b/services/core/java/com/android/server/biometrics/sensors/fingerprint/FingerprintUtils.java @@ -140,6 +140,22 @@ public class FingerprintUtils implements BiometricUtils<Fingerprint> { return getStateForUser(context, userId).isInvalidationInProgress(); } + @Override + public boolean hasValidBiometricUserState(Context context, int userId) { + return getStateForUser(context, userId).isInvalidBiometricState(); + } + + @Override + public void deleteStateForUser(int userId) { + synchronized (this) { + FingerprintUserState state = mUserStates.get(userId); + if (state != null) { + state.deleteBiometricFile(); + mUserStates.delete(userId); + } + } + } + private FingerprintUserState getStateForUser(Context ctx, int userId) { synchronized (this) { FingerprintUserState state = mUserStates.get(userId); diff --git a/services/core/java/com/android/server/biometrics/sensors/fingerprint/aidl/FingerprintInternalCleanupClient.java b/services/core/java/com/android/server/biometrics/sensors/fingerprint/aidl/FingerprintInternalCleanupClient.java index 5edc2ca080ad..1fc517906c58 100644 --- a/services/core/java/com/android/server/biometrics/sensors/fingerprint/aidl/FingerprintInternalCleanupClient.java +++ b/services/core/java/com/android/server/biometrics/sensors/fingerprint/aidl/FingerprintInternalCleanupClient.java @@ -22,9 +22,11 @@ import android.hardware.biometrics.BiometricAuthenticator; import android.hardware.biometrics.BiometricsProtoEnums; import android.hardware.fingerprint.Fingerprint; import android.os.IBinder; +import android.util.Slog; import com.android.server.biometrics.log.BiometricContext; import com.android.server.biometrics.log.BiometricLogger; +import com.android.server.biometrics.sensors.BiometricNotificationUtils; import com.android.server.biometrics.sensors.BiometricUtils; import com.android.server.biometrics.sensors.InternalCleanupClient; import com.android.server.biometrics.sensors.InternalEnumerateClient; @@ -42,6 +44,8 @@ import java.util.function.Supplier; public class FingerprintInternalCleanupClient extends InternalCleanupClient<Fingerprint, AidlSession> { + private static final String TAG = "FingerprintInternalCleanupClient"; + public FingerprintInternalCleanupClient(@NonNull Context context, @NonNull Supplier<AidlSession> lazyDaemon, int userId, @NonNull String owner, int sensorId, @@ -80,4 +84,16 @@ public class FingerprintInternalCleanupClient FingerprintUtils.getInstance(getSensorId()).addBiometricForUser( getContext(), getTargetUserId(), (Fingerprint) identifier); } + + @Override + public void handleInvalidBiometricState() { + Slog.d(TAG, "Invalid fingerprint user state: delete the state."); + mBiometricUtils.deleteStateForUser(getTargetUserId()); + BiometricNotificationUtils.showFingerprintLoeNotification(getContext()); + } + + @Override + protected int getModality() { + return BiometricsProtoEnums.MODALITY_FINGERPRINT; + } } diff --git a/services/core/java/com/android/server/crashrecovery/TEST_MAPPING b/services/core/java/com/android/server/crashrecovery/TEST_MAPPING index 537fb32523b5..615db345635c 100644 --- a/services/core/java/com/android/server/crashrecovery/TEST_MAPPING +++ b/services/core/java/com/android/server/crashrecovery/TEST_MAPPING @@ -1,9 +1,4 @@ { - "presubmit": [ - { - "name": "CrashRecoveryModuleTests" - } - ], "postsubmit": [ { "name": "FrameworksMockingServicesTests", @@ -12,6 +7,9 @@ "include-filter": "com.android.server.RescuePartyTest" } ] + }, + { + "name": "CrashRecoveryModuleTests" } ] }
\ No newline at end of file diff --git a/services/core/java/com/android/server/devicestate/DeviceStateManagerService.java b/services/core/java/com/android/server/devicestate/DeviceStateManagerService.java index 619aecf4156f..38e6d822477a 100644 --- a/services/core/java/com/android/server/devicestate/DeviceStateManagerService.java +++ b/services/core/java/com/android/server/devicestate/DeviceStateManagerService.java @@ -50,8 +50,7 @@ import android.hardware.devicestate.DeviceStateManager; import android.hardware.devicestate.DeviceStateManagerInternal; import android.hardware.devicestate.IDeviceStateManager; import android.hardware.devicestate.IDeviceStateManagerCallback; -import android.hardware.devicestate.feature.flags.FeatureFlags; -import android.hardware.devicestate.feature.flags.FeatureFlagsImpl; +import android.hardware.devicestate.feature.flags.Flags; import android.os.Binder; import android.os.Handler; import android.os.IBinder; @@ -190,9 +189,6 @@ public final class DeviceStateManagerService extends SystemService { @Nullable private OverrideRequest mRearDisplayPendingOverrideRequest; - @NonNull - private final FeatureFlags mFlags; - @VisibleForTesting interface SystemPropertySetter { void setDebugTracingDeviceStateProperty(String value); @@ -253,7 +249,6 @@ public final class DeviceStateManagerService extends SystemService { @NonNull SystemPropertySetter systemPropertySetter) { super(context); mSystemPropertySetter = systemPropertySetter; - mFlags = new FeatureFlagsImpl(); // We use the DisplayThread because this service indirectly drives // display (on/off) and window (position) events through its callbacks. DisplayThread displayThread = DisplayThread.get(); @@ -279,7 +274,7 @@ public final class DeviceStateManagerService extends SystemService { publishBinderService(Context.DEVICE_STATE_SERVICE, mBinderService); publishLocalService(DeviceStateManagerInternal.class, new LocalService()); - if (!mFlags.deviceStatePropertyMigration()) { + if (!Flags.deviceStatePropertyMigration()) { synchronized (mLock) { readStatesAvailableForRequestFromApps(); mFoldedDeviceStates = readFoldedStates(); @@ -848,7 +843,7 @@ public final class DeviceStateManagerService extends SystemService { OverrideRequest request = new OverrideRequest(token, callingPid, callingUid, deviceState.get(), flags, OVERRIDE_REQUEST_TYPE_EMULATED_STATE); - if (mFlags.deviceStatePropertyMigration()) { + if (Flags.deviceStatePropertyMigration()) { // If we don't have the CONTROL_DEVICE_STATE permission, we want to show the overlay if (!hasControlDeviceStatePermission && deviceState.get().hasProperty( PROPERTY_FEATURE_REAR_DISPLAY)) { @@ -988,16 +983,16 @@ public final class DeviceStateManagerService extends SystemService { * @param callingPid Process ID that is requesting this state change * @param state state that is being requested. */ - private void assertCanRequestDeviceState(int callingPid, int callingUid, int state) { + private void enforceRequestDeviceStatePermitted(int callingPid, int callingUid, int state) { final boolean isTopApp = isTopApp(callingPid); final boolean isForegroundApp = isForegroundApp(callingPid, callingUid); final boolean isStateAvailableForAppRequests = isStateAvailableForAppRequests(state); - final boolean canRequestState = isTopApp + final boolean isAllowedToRequestState = isTopApp && isForegroundApp && isStateAvailableForAppRequests; - if (!canRequestState) { + if (!isAllowedToRequestState) { getContext().enforceCallingOrSelfPermission(CONTROL_DEVICE_STATE, "Permission required to request device state, " + "or the call must come from the top app " @@ -1006,19 +1001,29 @@ public final class DeviceStateManagerService extends SystemService { } /** - * Checks if the process can control the device state. If the calling process ID is - * not the top app, then check if this process holds the CONTROL_DEVICE_STATE permission. + * Checks if the process can cancel a device state request. If the calling process ID is not + * both the top app and foregrounded nor does the process ID and userID match the IDs that made + * the device state request, then check if this process holds the CONTROL_DEVICE_STATE + * permission. * * @param callingPid Process ID that is requesting this state change * @param callingUid UID that is requesting this state change */ - private void assertCanControlDeviceState(int callingPid, int callingUid) { + private void enforceCancelDeviceStatePermitted(int callingPid, int callingUid) { final boolean isTopApp = isTopApp(callingPid); final boolean isForegroundApp = isForegroundApp(callingPid, callingUid); - final boolean canControlState = isTopApp && isForegroundApp; + boolean isAllowedToControlState = isTopApp && isForegroundApp; + + if (Flags.deviceStateRequesterCancelState()) { + synchronized (mLock) { + isAllowedToControlState = + isAllowedToControlState || doCallingIdsMatchOverrideRequestIdsLocked( + callingPid, callingUid); + } + } - if (!canControlState) { + if (!isAllowedToControlState) { getContext().enforceCallingOrSelfPermission(CONTROL_DEVICE_STATE, "Permission required to request device state, " + "or the call must come from the top app."); @@ -1052,9 +1057,19 @@ public final class DeviceStateManagerService extends SystemService { return topApp != null && topApp.getPid() == callingPid; } + /** + * Returns if the provided {@code callingPid} and {@code callingUid} match the same id's that + * requested the current device state override. + */ + @GuardedBy("mLock") + private boolean doCallingIdsMatchOverrideRequestIdsLocked(int callingPid, int callingUid) { + OverrideRequest request = mActiveOverride.orElse(null); + return request != null && request.getPid() == callingPid && request.getUid() == callingUid; + } + private boolean isStateAvailableForAppRequests(int state) { synchronized (mLock) { - if (mFlags.deviceStatePropertyMigration()) { + if (Flags.deviceStatePropertyMigration()) { Optional<DeviceState> deviceState = getStateLocked(state); return deviceState.isPresent() && deviceState.get().hasProperty( PROPERTY_POLICY_AVAILABLE_FOR_APP_REQUEST); @@ -1122,7 +1137,7 @@ public final class DeviceStateManagerService extends SystemService { */ @GuardedBy("mLock") private boolean isDeviceOpeningLocked(int newBaseState) { - if (mFlags.deviceStatePropertyMigration()) { + if (Flags.deviceStatePropertyMigration()) { final DeviceState currentBaseState = mBaseState.orElse(INVALID_DEVICE_STATE); final DeviceState newDeviceBaseState = getStateLocked(newBaseState).orElse( INVALID_DEVICE_STATE); @@ -1293,7 +1308,7 @@ public final class DeviceStateManagerService extends SystemService { // Allow top processes to request a device state change // If the calling process ID is not the top app, then we check if this process // holds a permission to CONTROL_DEVICE_STATE - assertCanRequestDeviceState(callingPid, callingUid, state); + enforceRequestDeviceStatePermitted(callingPid, callingUid, state); if (token == null) { throw new IllegalArgumentException("Request token must not be null."); @@ -1318,7 +1333,7 @@ public final class DeviceStateManagerService extends SystemService { // Allow top processes to cancel a device state change // If the calling process ID is not the top app, then we check if this process // holds a permission to CONTROL_DEVICE_STATE - assertCanControlDeviceState(callingPid, callingUid); + enforceCancelDeviceStatePermitted(callingPid, callingUid); final long callingIdentity = Binder.clearCallingIdentity(); try { diff --git a/services/core/java/com/android/server/display/AutomaticBrightnessController.java b/services/core/java/com/android/server/display/AutomaticBrightnessController.java index 7b5cff739ba1..226bdf54ce3b 100644 --- a/services/core/java/com/android/server/display/AutomaticBrightnessController.java +++ b/services/core/java/com/android/server/display/AutomaticBrightnessController.java @@ -579,6 +579,14 @@ public class AutomaticBrightnessController { return mCurrentBrightnessMapper.getMode(); } + /** + * @return The preset for this mapping strategy. Presets are used on devices that allow users + * to choose from a set of predefined options in display auto-brightness settings. + */ + public int getPreset() { + return mCurrentBrightnessMapper.getPreset(); + } + public boolean isInIdleMode() { return mCurrentBrightnessMapper.getMode() == AUTO_BRIGHTNESS_MODE_IDLE; } diff --git a/services/core/java/com/android/server/display/BrightnessMappingStrategy.java b/services/core/java/com/android/server/display/BrightnessMappingStrategy.java index 8405e0a52084..b0507fb78a41 100644 --- a/services/core/java/com/android/server/display/BrightnessMappingStrategy.java +++ b/services/core/java/com/android/server/display/BrightnessMappingStrategy.java @@ -140,10 +140,10 @@ public abstract class BrightnessMappingStrategy { builder.setShortTermModelLowerLuxMultiplier(SHORT_TERM_MODEL_THRESHOLD_RATIO); builder.setShortTermModelUpperLuxMultiplier(SHORT_TERM_MODEL_THRESHOLD_RATIO); return new PhysicalMappingStrategy(builder.build(), nitsRange, brightnessRange, - autoBrightnessAdjustmentMaxGamma, mode, displayWhiteBalanceController); + autoBrightnessAdjustmentMaxGamma, mode, preset, displayWhiteBalanceController); } else if (isValidMapping(luxLevels, brightnessLevels)) { return new SimpleMappingStrategy(luxLevels, brightnessLevels, - autoBrightnessAdjustmentMaxGamma, shortTermModelTimeout, mode); + autoBrightnessAdjustmentMaxGamma, shortTermModelTimeout, mode, preset); } else { return null; } @@ -394,6 +394,12 @@ public abstract class BrightnessMappingStrategy { abstract int getMode(); /** + * @return The preset for this mapping strategy. Presets are used on devices that allow users + * to choose from a set of predefined options in display auto-brightness settings. + */ + abstract int getPreset(); + + /** * Check if the short term model should be reset given the anchor lux the last * brightness change was made at and the current ambient lux. */ @@ -598,6 +604,8 @@ public abstract class BrightnessMappingStrategy { @AutomaticBrightnessController.AutomaticBrightnessMode private final int mMode; + private final int mPreset; + private Spline mSpline; private float mMaxGamma; private float mAutoBrightnessAdjustment; @@ -606,7 +614,8 @@ public abstract class BrightnessMappingStrategy { private long mShortTermModelTimeout; private SimpleMappingStrategy(float[] lux, float[] brightness, float maxGamma, - long timeout, @AutomaticBrightnessController.AutomaticBrightnessMode int mode) { + long timeout, @AutomaticBrightnessController.AutomaticBrightnessMode int mode, + int preset) { Preconditions.checkArgument(lux.length != 0 && brightness.length != 0, "Lux and brightness arrays must not be empty!"); Preconditions.checkArgument(lux.length == brightness.length, @@ -633,6 +642,7 @@ public abstract class BrightnessMappingStrategy { computeSpline(); mShortTermModelTimeout = timeout; mMode = mode; + mPreset = preset; } @Override @@ -766,6 +776,11 @@ public abstract class BrightnessMappingStrategy { } @Override + int getPreset() { + return mPreset; + } + + @Override float getUserLux() { return mUserLux; } @@ -837,6 +852,8 @@ public abstract class BrightnessMappingStrategy { @AutomaticBrightnessController.AutomaticBrightnessMode private final int mMode; + private final int mPreset; + // Previous short-term models and the times that they were computed stored for debugging // purposes private List<Spline> mPreviousBrightnessSplines = new ArrayList<>(); @@ -846,7 +863,7 @@ public abstract class BrightnessMappingStrategy { public PhysicalMappingStrategy(BrightnessConfiguration config, float[] nits, float[] brightness, float maxGamma, - @AutomaticBrightnessController.AutomaticBrightnessMode int mode, + @AutomaticBrightnessController.AutomaticBrightnessMode int mode, int preset, @Nullable DisplayWhiteBalanceController displayWhiteBalanceController) { Preconditions.checkArgument(nits.length != 0 && brightness.length != 0, @@ -860,6 +877,7 @@ public abstract class BrightnessMappingStrategy { PowerManager.BRIGHTNESS_MIN, PowerManager.BRIGHTNESS_MAX, "brightness"); mMode = mode; + mPreset = preset; mMaxGamma = maxGamma; mAutoBrightnessAdjustment = 0; mUserLux = INVALID_LUX; @@ -1073,6 +1091,11 @@ public abstract class BrightnessMappingStrategy { } @Override + int getPreset() { + return mPreset; + } + + @Override float getUserLux() { return mUserLux; } diff --git a/services/core/java/com/android/server/display/BrightnessRangeController.java b/services/core/java/com/android/server/display/BrightnessRangeController.java index 515e70495f9e..8a3e39257145 100644 --- a/services/core/java/com/android/server/display/BrightnessRangeController.java +++ b/services/core/java/com/android/server/display/BrightnessRangeController.java @@ -60,7 +60,7 @@ class BrightnessRangeController { mModeChangeCallback = modeChangeCallback; mHdrClamper = hdrClamper; mNormalBrightnessModeController = normalBrightnessModeController; - mUseHdrClamper = flags.isHdrClamperEnabled(); + mUseHdrClamper = flags.isHdrClamperEnabled() && !flags.useNewHdrBrightnessModifier(); mUseNbmController = flags.isNbmControllerEnabled(); if (mUseNbmController) { mNormalBrightnessModeController.resetNbmData( diff --git a/services/core/java/com/android/server/display/DisplayDeviceConfig.java b/services/core/java/com/android/server/display/DisplayDeviceConfig.java index ed6ed60a6806..cc115f13f5e3 100644 --- a/services/core/java/com/android/server/display/DisplayDeviceConfig.java +++ b/services/core/java/com/android/server/display/DisplayDeviceConfig.java @@ -588,22 +588,43 @@ import javax.xml.datatype.DatatypeConfigurationException; * <minorVersion>0</minorVersion> * </usiVersion> * <evenDimmer enabled="true"> - * <transitionPoint>0.1</transitionPoint> - * - * <nits>0.2</nits> - * <nits>2.0</nits> - * <nits>500.0</nits> - * <nits>1000.0</nits> - * - * <backlight>0</backlight> - * <backlight>0.0001</backlight> - * <backlight>0.5</backlight> - * <backlight>1.0</backlight> - * - * <brightness>0</brightness> - * <brightness>0.1</brightness> - * <brightness>0.5</brightness> - * <brightness>1.0</brightness> + * <transitionPoint>0.1</transitionPoint> + * <brightnessMapping> + * <brightnessPoint> + * <nits>0.2</nits> + * <backlight>0</backlight> + * <brightness>0</brightness> + * </brightnessPoint> + * <brightnessPoint> + * <nits>2.0</nits> + * <backlight>0.01</backlight> + * <brightness>0.002</brightness> + * </brightnessPoint> + * <brightnessPoint> + * <nits>500.0</nits> + * <backlight>0.5</backlight> + * <brightness>0.5</brightness> + * </brightnessPoint> + * <brightnessPoint> + * <nits>1000</nits> + * <backlight>1.0</backlight> + * <brightness>1.0</brightness> + * </brightnessPoint> + * </brightnessMapping> + * <luxToMinimumNitsMap> + * <point> + * <value>10</value> + * <nits>0.3</nits> + * </point> + * <point> + * <value>50</value> + * <nits>0.7</nits> + * </point> + * <point> + * <value>100</value> + * <nits>1.0</nits> + * </point> + * </luxToMinimumNitsMap> * </evenDimmer> * <screenBrightnessCapForWearBedtimeMode>0.1</screenBrightnessCapForWearBedtimeMode> * <idleScreenRefreshRateTimeout> diff --git a/services/core/java/com/android/server/display/DisplayManagerService.java b/services/core/java/com/android/server/display/DisplayManagerService.java index 2cec869c290e..9e905abd78ed 100644 --- a/services/core/java/com/android/server/display/DisplayManagerService.java +++ b/services/core/java/com/android/server/display/DisplayManagerService.java @@ -722,6 +722,7 @@ public final class DisplayManagerService extends SystemService { if (userSwitching) { mCurrentUserId = newUserId; } + mDisplayModeDirector.onSwitchUser(); mLogicalDisplayMapper.forEachLocked(logicalDisplay -> { if (logicalDisplay.getDisplayInfoLocked().type != Display.TYPE_INTERNAL) { return; diff --git a/services/core/java/com/android/server/display/DisplayPowerController.java b/services/core/java/com/android/server/display/DisplayPowerController.java index 8b21d98045dd..480c370aff86 100644 --- a/services/core/java/com/android/server/display/DisplayPowerController.java +++ b/services/core/java/com/android/server/display/DisplayPowerController.java @@ -702,6 +702,17 @@ final class DisplayPowerController implements AutomaticBrightnessController.Call private void handleOnSwitchUser(@UserIdInt int newUserId, int userSerial, float newBrightness) { Slog.i(mTag, "Switching user newUserId=" + newUserId + " userSerial=" + userSerial + " newBrightness=" + newBrightness); + + if (mAutomaticBrightnessController != null) { + int autoBrightnessPreset = Settings.System.getIntForUser(mContext.getContentResolver(), + Settings.System.SCREEN_BRIGHTNESS_FOR_ALS, + Settings.System.SCREEN_BRIGHTNESS_AUTOMATIC_NORMAL, + UserHandle.USER_CURRENT); + if (autoBrightnessPreset != mAutomaticBrightnessController.getPreset()) { + setUpAutoBrightness(mContext, mHandler); + } + } + handleBrightnessModeChange(); if (mBrightnessTracker != null) { mBrightnessTracker.onSwitchUser(newUserId); @@ -714,6 +725,7 @@ final class DisplayPowerController implements AutomaticBrightnessController.Call if (mAutomaticBrightnessController != null) { mAutomaticBrightnessController.resetShortTermModel(); } + mBrightnessClamperController.onUserSwitch(); sendUpdatePowerState(); } @@ -1009,7 +1021,7 @@ final class DisplayPowerController implements AutomaticBrightnessController.Call if (mFlags.areAutoBrightnessModesEnabled()) { mContext.getContentResolver().registerContentObserver( Settings.System.getUriFor(Settings.System.SCREEN_BRIGHTNESS_FOR_ALS), - /* notifyForDescendants= */ false, mSettingsObserver, UserHandle.USER_CURRENT); + /* notifyForDescendants= */ false, mSettingsObserver, UserHandle.USER_ALL); } handleBrightnessModeChange(); } diff --git a/services/core/java/com/android/server/display/brightness/clamper/BrightnessClamperController.java b/services/core/java/com/android/server/display/brightness/clamper/BrightnessClamperController.java index 9324fc1c4e06..12c3197aba2a 100644 --- a/services/core/java/com/android/server/display/brightness/clamper/BrightnessClamperController.java +++ b/services/core/java/com/android/server/display/brightness/clamper/BrightnessClamperController.java @@ -71,6 +71,7 @@ public class BrightnessClamperController { private final List<DisplayDeviceDataListener> mDisplayDeviceDataListeners = new ArrayList<>(); private final List<StatefulModifier> mStatefulModifiers = new ArrayList<>(); + private final List<UserSwitchListener> mUserSwitchListeners = new ArrayList<>(); private ModifiersAggregatedState mModifiersAggregatedState = new ModifiersAggregatedState(); private final DeviceConfig.OnPropertiesChangedListener mOnPropertiesChangedListener; @@ -127,6 +128,9 @@ public class BrightnessClamperController { if (m instanceof StatefulModifier s) { mStatefulModifiers.add(s); } + if (m instanceof UserSwitchListener l) { + mUserSwitchListeners.add(l); + } }); mOnPropertiesChangedListener = properties -> mClampers.forEach(BrightnessClamper::onDeviceConfigChanged); @@ -209,6 +213,13 @@ public class BrightnessClamperController { } /** + * Called when the user switches. + */ + public void onUserSwitch() { + mUserSwitchListeners.forEach(listener -> listener.onSwitchUser()); + } + + /** * Used to dump ClampersController state. */ public void dump(PrintWriter writer) { @@ -466,6 +477,13 @@ public class BrightnessClamperController { } /** + * A clamper/modifier should implement this interface if it reads user-specific settings + */ + interface UserSwitchListener { + void onSwitchUser(); + } + + /** * StatefulModifiers contribute to AggregatedState, that is used to decide if brightness * adjustement is needed */ diff --git a/services/core/java/com/android/server/display/brightness/clamper/BrightnessLowLuxModifier.java b/services/core/java/com/android/server/display/brightness/clamper/BrightnessLowLuxModifier.java index 951980adac8c..c3596c3e77fe 100644 --- a/services/core/java/com/android/server/display/brightness/clamper/BrightnessLowLuxModifier.java +++ b/services/core/java/com/android/server/display/brightness/clamper/BrightnessLowLuxModifier.java @@ -41,7 +41,8 @@ import java.io.PrintWriter; * Class used to prevent the screen brightness dipping below a certain value, based on current * lux conditions and user preferred minimum. */ -public class BrightnessLowLuxModifier extends BrightnessModifier { +public class BrightnessLowLuxModifier extends BrightnessModifier implements + BrightnessClamperController.UserSwitchListener { // To enable these logs, run: // 'adb shell setprop persist.log.tag.BrightnessLowLuxModifier DEBUG && adb reboot' @@ -81,10 +82,9 @@ public class BrightnessLowLuxModifier extends BrightnessModifier { */ @VisibleForTesting public void recalculateLowerBound() { - int userId = UserHandle.USER_CURRENT; float settingNitsLowerBound = Settings.Secure.getFloatForUser( mContentResolver, Settings.Secure.EVEN_DIMMER_MIN_NITS, - /* def= */ MIN_NITS_DEFAULT, userId); + /* def= */ MIN_NITS_DEFAULT, UserHandle.USER_CURRENT); boolean isActive = isSettingEnabled() && mAmbientLux != BrightnessMappingStrategy.INVALID_LUX; @@ -190,6 +190,11 @@ public class BrightnessLowLuxModifier extends BrightnessModifier { } @Override + public void onSwitchUser() { + recalculateLowerBound(); + } + + @Override public void dump(PrintWriter pw) { pw.println("BrightnessLowLuxModifier:"); pw.println(" mIsActive=" + mIsActive); @@ -221,10 +226,10 @@ public class BrightnessLowLuxModifier extends BrightnessModifier { super(handler); mContentResolver.registerContentObserver( Settings.Secure.getUriFor(Settings.Secure.EVEN_DIMMER_MIN_NITS), - false, this); + false, this, UserHandle.USER_ALL); mContentResolver.registerContentObserver( Settings.Secure.getUriFor(Settings.Secure.EVEN_DIMMER_ACTIVATED), - false, this); + false, this, UserHandle.USER_ALL); } @Override diff --git a/services/core/java/com/android/server/display/brightness/clamper/HdrBrightnessModifier.java b/services/core/java/com/android/server/display/brightness/clamper/HdrBrightnessModifier.java index 5e44cc357b28..ae1801ccea74 100644 --- a/services/core/java/com/android/server/display/brightness/clamper/HdrBrightnessModifier.java +++ b/services/core/java/com/android/server/display/brightness/clamper/HdrBrightnessModifier.java @@ -31,6 +31,7 @@ import com.android.internal.annotations.VisibleForTesting; import com.android.internal.display.BrightnessSynchronizer; import com.android.server.display.DisplayBrightnessState; import com.android.server.display.DisplayDeviceConfig; +import com.android.server.display.brightness.BrightnessReason; import com.android.server.display.config.HdrBrightnessData; import java.io.PrintWriter; @@ -99,7 +100,7 @@ public class HdrBrightnessModifier implements BrightnessStateModifier, mMaxBrightness = mPendingMaxBrightness; mClamperChangeListener.onChanged(); }; - onDisplayChanged(displayData); + mHandler.post(() -> onDisplayChanged(displayData)); } // Called in DisplayControllerHandler @@ -120,6 +121,8 @@ public class HdrBrightnessModifier implements BrightnessStateModifier, stateBuilder.setHdrBrightness(hdrBrightness); stateBuilder.setCustomAnimationRate(mTransitionRate); + stateBuilder.getBrightnessReason().addModifier(BrightnessReason.MODIFIER_HDR); + // transition rate applied, reset mTransitionRate = CUSTOM_ANIMATION_RATE_NOT_SET; } @@ -168,10 +171,18 @@ public class HdrBrightnessModifier implements BrightnessStateModifier, } } + // Called in DisplayControllerHandler @Override public void onDisplayChanged(BrightnessClamperController.DisplayDeviceData displayData) { - mHandler.post(() -> onDisplayChanged(displayData.mDisplayToken, displayData.mWidth, - displayData.mHeight, displayData.mDisplayDeviceConfig)); + mDisplayDeviceConfig = displayData.mDisplayDeviceConfig; + mScreenSize = (float) displayData.mWidth * displayData.mHeight; + HdrBrightnessData data = mDisplayDeviceConfig.getHdrBrightnessData(); + if (data == null) { + unregisterHdrListener(); + } else { + registerHdrListener(displayData.mDisplayToken); + } + recalculate(data, mMaxDesiredHdrRatio); } // Called in DisplayControllerHandler, when any modifier state changes @@ -215,20 +226,6 @@ public class HdrBrightnessModifier implements BrightnessStateModifier, } // Called in DisplayControllerHandler - private void onDisplayChanged(IBinder displayToken, int width, int height, - DisplayDeviceConfig config) { - mDisplayDeviceConfig = config; - mScreenSize = (float) width * height; - HdrBrightnessData data = config.getHdrBrightnessData(); - if (data == null) { - unregisterHdrListener(); - } else { - registerHdrListener(displayToken); - } - recalculate(data, mMaxDesiredHdrRatio); - } - - // Called in DisplayControllerHandler private void recalculate(@Nullable HdrBrightnessData data, float maxDesiredHdrRatio) { Mode newMode = recalculateMode(data); // if HDR mode changed, notify changed @@ -258,6 +255,10 @@ public class HdrBrightnessModifier implements BrightnessStateModifier, if (data == null) { return Mode.NO_HDR; } + // no HDR layer present + if (mHdrLayerSize == DEFAULT_HDR_LAYER_SIZE) { + return Mode.NO_HDR; + } // HDR layer < minHdr % for Nbm if (mHdrLayerSize < mScreenSize * data.minimumHdrPercentOfScreenForNbm) { return Mode.NO_HDR; diff --git a/services/core/java/com/android/server/display/brightness/clamper/LightSensorController.java b/services/core/java/com/android/server/display/brightness/clamper/LightSensorController.java index d89dd28c4a89..b219cb1bc15c 100644 --- a/services/core/java/com/android/server/display/brightness/clamper/LightSensorController.java +++ b/services/core/java/com/android/server/display/brightness/clamper/LightSensorController.java @@ -62,6 +62,9 @@ public class LightSensorController { private final SensorEventListener mLightSensorEventListener = new SensorEventListener() { @Override public void onSensorChanged(SensorEvent event) { + if (event.sensor != mRegisteredLightSensor) { + return; + } long now = mInjector.getTime(); mAmbientFilter.addValue(TimeUnit.NANOSECONDS.toMillis(event.timestamp), event.values[0]); @@ -95,15 +98,13 @@ public class LightSensorController { if (mRegisteredLightSensor == mLightSensor) { return; } + if (mLightSensor != null) { + mSensorManager.registerListener(mLightSensorEventListener, + mLightSensor, mLightSensorRate * 1000, mHandler); + } if (mRegisteredLightSensor != null) { stop(); } - if (mLightSensor == null) { - return; - } - - mSensorManager.registerListener(mLightSensorEventListener, - mLightSensor, mLightSensorRate * 1000, mHandler); mRegisteredLightSensor = mLightSensor; if (DEBUG) { @@ -115,7 +116,7 @@ public class LightSensorController { if (mRegisteredLightSensor == null) { return; } - mSensorManager.unregisterListener(mLightSensorEventListener); + mSensorManager.unregisterListener(mLightSensorEventListener, mRegisteredLightSensor); mRegisteredLightSensor = null; mAmbientFilter.clear(); mLightSensorListener.onAmbientLuxChange(INVALID_LUX); diff --git a/services/core/java/com/android/server/display/mode/DisplayModeDirector.java b/services/core/java/com/android/server/display/mode/DisplayModeDirector.java index d610f086b3b5..5e471c82e108 100644 --- a/services/core/java/com/android/server/display/mode/DisplayModeDirector.java +++ b/services/core/java/com/android/server/display/mode/DisplayModeDirector.java @@ -121,6 +121,7 @@ public class DisplayModeDirector { private static final int MSG_HIGH_BRIGHTNESS_THRESHOLDS_CHANGED = 6; private static final int MSG_REFRESH_RATE_IN_HBM_SUNLIGHT_CHANGED = 7; private static final int MSG_REFRESH_RATE_IN_HBM_HDR_CHANGED = 8; + private static final int MSG_SWITCH_USER = 9; private final Object mLock = new Object(); private final Context mContext; @@ -564,6 +565,13 @@ public class DisplayModeDirector { } /** + * Called when the user switches. + */ + public void onSwitchUser() { + mHandler.obtainMessage(MSG_SWITCH_USER).sendToTarget(); + } + + /** * Print the object's state and debug information into the given stream. * * @param pw The stream to dump information to. @@ -789,6 +797,13 @@ public class DisplayModeDirector { mHbmObserver.onDeviceConfigRefreshRateInHbmHdrChanged(refreshRateInHbmHdr); break; } + + case MSG_SWITCH_USER: { + synchronized (mLock) { + mSettingsObserver.updateRefreshRateSettingLocked(); + mSettingsObserver.updateModeSwitchingTypeSettingLocked(); + } + } } } } @@ -1012,10 +1027,10 @@ public class DisplayModeDirector { final ContentResolver cr = mContext.getContentResolver(); mInjector.registerPeakRefreshRateObserver(cr, this); mInjector.registerMinRefreshRateObserver(cr, this); - cr.registerContentObserver(mLowPowerModeSetting, false /*notifyDescendants*/, this, - UserHandle.USER_SYSTEM); - cr.registerContentObserver(mMatchContentFrameRateSetting, false /*notifyDescendants*/, - this); + cr.registerContentObserver(mLowPowerModeSetting, /* notifyDescendants= */ false, this, + UserHandle.USER_ALL); + cr.registerContentObserver(mMatchContentFrameRateSetting, + /* notifyDescendants= */ false, this, UserHandle.USER_ALL); mInjector.registerDisplayListener(mDisplayListener, mHandler); float deviceConfigDefaultPeakRefresh = @@ -1156,14 +1171,15 @@ public class DisplayModeDirector { float highestRefreshRate = getMaxRefreshRateLocked(displayId); float minRefreshRate = Settings.System.getFloatForUser(cr, - Settings.System.MIN_REFRESH_RATE, 0f, cr.getUserId()); + Settings.System.MIN_REFRESH_RATE, 0f, UserHandle.USER_CURRENT); if (Float.isInfinite(minRefreshRate)) { // Infinity means that we want the highest possible refresh rate minRefreshRate = highestRefreshRate; } float peakRefreshRate = Settings.System.getFloatForUser(cr, - Settings.System.PEAK_REFRESH_RATE, mDefaultPeakRefreshRate, cr.getUserId()); + Settings.System.PEAK_REFRESH_RATE, mDefaultPeakRefreshRate, + UserHandle.USER_CURRENT); if (Float.isInfinite(peakRefreshRate)) { // Infinity means that we want the highest possible refresh rate peakRefreshRate = highestRefreshRate; @@ -1234,9 +1250,9 @@ public class DisplayModeDirector { private void updateModeSwitchingTypeSettingLocked() { final ContentResolver cr = mContext.getContentResolver(); - int switchingType = Settings.Secure.getIntForUser( - cr, Settings.Secure.MATCH_CONTENT_FRAME_RATE, mModeSwitchingType /*default*/, - cr.getUserId()); + int switchingType = Settings.Secure.getIntForUser(cr, + Settings.Secure.MATCH_CONTENT_FRAME_RATE, /* default= */ mModeSwitchingType, + UserHandle.USER_CURRENT); if (switchingType != mModeSwitchingType) { mModeSwitchingType = switchingType; notifyDesiredDisplayModeSpecsChangedLocked(); @@ -3033,14 +3049,14 @@ public class DisplayModeDirector { public void registerPeakRefreshRateObserver(@NonNull ContentResolver cr, @NonNull ContentObserver observer) { cr.registerContentObserver(PEAK_REFRESH_RATE_URI, false /*notifyDescendants*/, - observer, UserHandle.USER_SYSTEM); + observer, UserHandle.USER_ALL); } @Override public void registerMinRefreshRateObserver(@NonNull ContentResolver cr, @NonNull ContentObserver observer) { cr.registerContentObserver(MIN_REFRESH_RATE_URI, false /*notifyDescendants*/, - observer, UserHandle.USER_SYSTEM); + observer, UserHandle.USER_ALL); } @Override diff --git a/services/core/java/com/android/server/dreams/DreamManagerService.java b/services/core/java/com/android/server/dreams/DreamManagerService.java index d43e783cad41..a3b77e897117 100644 --- a/services/core/java/com/android/server/dreams/DreamManagerService.java +++ b/services/core/java/com/android/server/dreams/DreamManagerService.java @@ -543,18 +543,20 @@ public final class DreamManagerService extends SystemService { } private void startDozingInternal(IBinder token, int screenState, - @Display.StateReason int reason, int screenBrightness) { + @Display.StateReason int reason, float screenBrightnessFloat, int screenBrightnessInt) { Slog.d(TAG, "Dream requested to start dozing: " + token + ", screenState=" + Display.stateToString(screenState) + ", reason=" + Display.stateReasonToString(reason) - + ", screenBrightness=" + screenBrightness); + + ", screenBrightnessFloat=" + screenBrightnessFloat + + ", screenBrightnessInt=" + screenBrightnessInt); synchronized (mLock) { if (mCurrentDream != null && mCurrentDream.token == token && mCurrentDream.canDoze) { mCurrentDream.dozeScreenState = screenState; - mCurrentDream.dozeScreenBrightness = screenBrightness; + mCurrentDream.dozeScreenBrightness = screenBrightnessInt; + mCurrentDream.dozeScreenBrightnessFloat = screenBrightnessFloat; mPowerManagerInternal.setDozeOverrideFromDreamManager( - screenState, reason, screenBrightness); + screenState, reason, screenBrightnessFloat, screenBrightnessInt); if (!mCurrentDream.isDozing) { mCurrentDream.isDozing = true; mDozeWakeLock.acquire(); @@ -575,6 +577,7 @@ public final class DreamManagerService extends SystemService { mPowerManagerInternal.setDozeOverrideFromDreamManager( Display.STATE_UNKNOWN, Display.STATE_REASON_DREAM_MANAGER, + PowerManager.BRIGHTNESS_INVALID_FLOAT, PowerManager.BRIGHTNESS_DEFAULT); } } @@ -1095,7 +1098,7 @@ public final class DreamManagerService extends SystemService { @Override // Binder call public void startDozing( IBinder token, int screenState, @Display.StateReason int reason, - int screenBrightness) { + float screenBrightnessFloat, int screeBrightnessInt) { // Requires no permission, called by Dream from an arbitrary process. if (token == null) { throw new IllegalArgumentException("token must not be null"); @@ -1103,7 +1106,8 @@ public final class DreamManagerService extends SystemService { final long ident = Binder.clearCallingIdentity(); try { - startDozingInternal(token, screenState, reason, screenBrightness); + startDozingInternal(token, screenState, reason, screenBrightnessFloat, + screeBrightnessInt); } finally { Binder.restoreCallingIdentity(ident); } @@ -1112,7 +1116,7 @@ public final class DreamManagerService extends SystemService { @Override // Binder call public void startDozingOneway( IBinder token, int screenState, @Display.StateReason int reason, - int screenBrightness) { + float screenBrightnessFloat, int screeBrightnessInt) { // Requires no permission, called by Dream from an arbitrary process. if (token == null) { throw new IllegalArgumentException("token must not be null"); @@ -1120,7 +1124,8 @@ public final class DreamManagerService extends SystemService { final long ident = Binder.clearCallingIdentity(); try { - startDozingInternal(token, screenState, reason, screenBrightness); + startDozingInternal(token, screenState, reason, screenBrightnessFloat, + screeBrightnessInt); } finally { Binder.restoreCallingIdentity(ident); } @@ -1277,6 +1282,7 @@ public final class DreamManagerService extends SystemService { public boolean isWaking = false; public int dozeScreenState = Display.STATE_UNKNOWN; public int dozeScreenBrightness = PowerManager.BRIGHTNESS_DEFAULT; + public float dozeScreenBrightnessFloat = PowerManager.BRIGHTNESS_INVALID_FLOAT; DreamRecord(ComponentName name, int userId, boolean isPreview, boolean canDoze) { this.name = name; @@ -1297,6 +1303,7 @@ public final class DreamManagerService extends SystemService { + ", isWaking=" + isWaking + ", dozeScreenState=" + dozeScreenState + ", dozeScreenBrightness=" + dozeScreenBrightness + + ", dozeScreenBrightnessFloat=" + dozeScreenBrightnessFloat + '}'; } } diff --git a/services/core/java/com/android/server/hdmi/HdmiCecMessageValidator.java b/services/core/java/com/android/server/hdmi/HdmiCecMessageValidator.java index 3c3bdd5b69f6..7746276ac505 100644 --- a/services/core/java/com/android/server/hdmi/HdmiCecMessageValidator.java +++ b/services/core/java/com/android/server/hdmi/HdmiCecMessageValidator.java @@ -769,6 +769,7 @@ public class HdmiCecMessageValidator { * @return true if the UI Broadcast type is valid */ private static boolean isValidUiBroadcastType(int value) { + value = value & 0xFF; return ((value == 0x00) || (value == 0x01) || (value == 0x10) diff --git a/services/core/java/com/android/server/hdmi/RequestActiveSourceAction.java b/services/core/java/com/android/server/hdmi/RequestActiveSourceAction.java index 539a00db45b8..a33d70a9b876 100644 --- a/services/core/java/com/android/server/hdmi/RequestActiveSourceAction.java +++ b/services/core/java/com/android/server/hdmi/RequestActiveSourceAction.java @@ -19,6 +19,7 @@ package com.android.server.hdmi; import android.hardware.hdmi.HdmiControlManager; import android.hardware.hdmi.IHdmiControlCallback; import android.util.Slog; +import com.android.internal.annotations.VisibleForTesting; /** * Feature action that sends <Request Active Source> message and waits for <Active Source> on TV @@ -39,6 +40,10 @@ public class RequestActiveSourceAction extends HdmiCecFeatureAction { // Number of retries <Request Active Source> is sent if no device answers this message. private static final int MAX_SEND_RETRY_COUNT = 1; + // Timeout to wait for the LauncherX API call to be completed. + @VisibleForTesting + protected static final int TIMEOUT_WAIT_FOR_LAUNCHERX_API_CALL_MS = 10000; + private int mSendRetryCount = 0; @@ -55,7 +60,7 @@ public class RequestActiveSourceAction extends HdmiCecFeatureAction { // We wait for default timeout to allow the message triggered by the LauncherX API call to // be sent by the TV and another default timeout in case the message has to be answered // (e.g. TV sent a <Set Stream Path> or <Routing Change>). - addTimer(mState, HdmiConfig.TIMEOUT_MS * 2); + addTimer(mState, TIMEOUT_WAIT_FOR_LAUNCHERX_API_CALL_MS); return true; } diff --git a/services/core/java/com/android/server/input/InputManagerService.java b/services/core/java/com/android/server/input/InputManagerService.java index f813997a8fec..a06ad145100d 100644 --- a/services/core/java/com/android/server/input/InputManagerService.java +++ b/services/core/java/com/android/server/input/InputManagerService.java @@ -1254,14 +1254,15 @@ public class InputManagerService extends IInputManager.Stub /** * Start drag and drop. * - * @param fromChannel The input channel that is currently receiving a touch gesture that should - * be turned into the drag pointer. - * @param dragAndDropChannel The input channel associated with the system drag window. + * @param fromChannelToken The token of the input channel that is currently receiving a touch + * gesture that should be turned into the drag pointer. + * @param dragAndDropChannelToken The token of the input channel associated with the system drag + * window. * @return true if drag and drop was successfully started, false otherwise. */ public boolean startDragAndDrop(@NonNull IBinder fromChannelToken, - @NonNull InputChannel dragAndDropChannel) { - return mNative.transferTouchGesture(fromChannelToken, dragAndDropChannel.getToken(), + @NonNull IBinder dragAndDropChannelToken) { + return mNative.transferTouchGesture(fromChannelToken, dragAndDropChannelToken, true /* isDragDrop */); } diff --git a/services/core/java/com/android/server/inputmethod/AdditionalSubtypeMapRepository.java b/services/core/java/com/android/server/inputmethod/AdditionalSubtypeMapRepository.java index 99f4747227ae..b08f9175a7a8 100644 --- a/services/core/java/com/android/server/inputmethod/AdditionalSubtypeMapRepository.java +++ b/services/core/java/com/android/server/inputmethod/AdditionalSubtypeMapRepository.java @@ -38,10 +38,11 @@ import java.util.concurrent.locks.ReentrantLock; final class AdditionalSubtypeMapRepository { private static final String TAG = "AdditionalSubtypeMapRepository"; - // TODO(b/352594784): Should we user other lock primitives? - @GuardedBy("sPerUserMap") + private static final Object sMutationLock = new Object(); + @NonNull - private static final SparseArray<AdditionalSubtypeMap> sPerUserMap = new SparseArray<>(); + private static volatile ImmutableSparseArray<AdditionalSubtypeMap> sPerUserMap = + ImmutableSparseArray.empty(); record WriteTask(@UserIdInt int userId, @NonNull AdditionalSubtypeMap subtypeMap, @NonNull InputMethodMap inputMethodMap) { @@ -198,7 +199,7 @@ final class AdditionalSubtypeMapRepository { /** * Returns {@link AdditionalSubtypeMap} for the given user. * - * <p>This method is expected be called after {@link #ensureInitializedAndGet(int)}. Otherwise + * <p>This method is expected be called after {@link #initializeIfNecessary(int)}. Otherwise * {@link AdditionalSubtypeMap#EMPTY_MAP} will be returned.</p> * * @param userId the user to be queried about @@ -207,10 +208,7 @@ final class AdditionalSubtypeMapRepository { @AnyThread @NonNull static AdditionalSubtypeMap get(@UserIdInt int userId) { - final AdditionalSubtypeMap map; - synchronized (sPerUserMap) { - map = sPerUserMap.get(userId); - } + final AdditionalSubtypeMap map = sPerUserMap.get(userId); if (map == null) { Slog.e(TAG, "get(userId=" + userId + ") is called before loadInitialDataAndGet()." + " Returning an empty map"); @@ -220,28 +218,24 @@ final class AdditionalSubtypeMapRepository { } /** - * Ensures that {@link AdditionalSubtypeMap} is initialized for the given user. Load it from - * the persistent storage if {@link #putAndSave(int, AdditionalSubtypeMap, InputMethodMap)} has - * not been called yet. + * Ensures that {@link AdditionalSubtypeMap} is initialized for the given user. * * @param userId the user to be initialized - * @return {@link AdditionalSubtypeMap} that is associated with the given user. If - * {@link #putAndSave(int, AdditionalSubtypeMap, InputMethodMap)} is already called - * then the given {@link AdditionalSubtypeMap}. */ @AnyThread @NonNull - static AdditionalSubtypeMap ensureInitializedAndGet(@UserIdInt int userId) { + static void initializeIfNecessary(@UserIdInt int userId) { + if (sPerUserMap.contains(userId)) { + // Fast-pass. If putAndSave() is already called, then do nothing. + return; + } final var map = AdditionalSubtypeUtils.load(userId); - synchronized (sPerUserMap) { - final AdditionalSubtypeMap previous = sPerUserMap.get(userId); - // If putAndSave() has already been called, then use it. - if (previous != null) { - return previous; + synchronized (sMutationLock) { + // Check the condition again. + if (!sPerUserMap.contains(userId)) { + sPerUserMap = sPerUserMap.cloneWithPutOrSelf(userId, map); } - sPerUserMap.put(userId, map); } - return map; } /** @@ -255,12 +249,8 @@ final class AdditionalSubtypeMapRepository { @AnyThread static void putAndSave(@UserIdInt int userId, @NonNull AdditionalSubtypeMap map, @NonNull InputMethodMap inputMethodMap) { - synchronized (sPerUserMap) { - final AdditionalSubtypeMap previous = sPerUserMap.get(userId); - if (previous == map) { - return; - } - sPerUserMap.put(userId, map); + synchronized (sMutationLock) { + sPerUserMap = sPerUserMap.cloneWithPutOrSelf(userId, map); sWriter.scheduleWriteTask(userId, map, inputMethodMap); } } @@ -277,9 +267,9 @@ final class AdditionalSubtypeMapRepository { @AnyThread static void remove(@UserIdInt int userId) { - synchronized (sPerUserMap) { + synchronized (sMutationLock) { sWriter.onUserRemoved(userId); - sPerUserMap.remove(userId); + sPerUserMap = sPerUserMap.cloneWithRemoveOrSelf(userId); } } } diff --git a/services/core/java/com/android/server/inputmethod/IInputMethodManagerImpl.java b/services/core/java/com/android/server/inputmethod/IInputMethodManagerImpl.java index a7280e6e99b4..58e345207edd 100644 --- a/services/core/java/com/android/server/inputmethod/IInputMethodManagerImpl.java +++ b/services/core/java/com/android/server/inputmethod/IInputMethodManagerImpl.java @@ -71,7 +71,20 @@ final class IInputMethodManagerImpl extends IInputMethodManager.Stub { @Retention(SOURCE) @Target({METHOD}) @interface PermissionVerified { + /** + * The name of the permission that is verified, if precisely one permission is required. + * If more than one permission is required, specify either {@link #allOf()} instead. + * + * <p>If specified, {@link #allOf()} must both be {@code null}.</p> + */ String value() default ""; + + /** + * Specifies a list of permission names that are all required. + * + * <p>If specified, {@link #value()} must both be {@code null}.</p> + */ + String[] allOf() default {}; } @BinderThread @@ -132,13 +145,17 @@ final class IInputMethodManagerImpl extends IInputMethodManager.Stub { void showInputMethodPickerFromClient(IInputMethodClient client, int auxiliarySubtypeMode); - @PermissionVerified(Manifest.permission.WRITE_SECURE_SETTINGS) + @PermissionVerified(allOf = { + Manifest.permission.INTERACT_ACROSS_USERS_FULL, + Manifest.permission.WRITE_SECURE_SETTINGS}) void showInputMethodPickerFromSystem(int auxiliarySubtypeMode, int displayId); @PermissionVerified(Manifest.permission.TEST_INPUT_METHOD) boolean isInputMethodPickerShownForTest(); - @PermissionVerified(Manifest.permission.WRITE_SECURE_SETTINGS) + @PermissionVerified(allOf = { + Manifest.permission.INTERACT_ACROSS_USERS_FULL, + Manifest.permission.WRITE_SECURE_SETTINGS}) void onImeSwitchButtonClickFromSystem(int displayId); InputMethodSubtype getCurrentInputMethodSubtype(@UserIdInt int userId); @@ -153,8 +170,10 @@ final class IInputMethodManagerImpl extends IInputMethodManager.Stub { void reportPerceptibleAsync(IBinder windowToken, boolean perceptible); - @PermissionVerified(Manifest.permission.INTERNAL_SYSTEM_WINDOW) - void removeImeSurface(); + @PermissionVerified(allOf = { + Manifest.permission.INTERACT_ACROSS_USERS_FULL, + Manifest.permission.INTERNAL_SYSTEM_WINDOW}) + void removeImeSurface(int displayId); void removeImeSurfaceFromWindowAsync(IBinder windowToken); @@ -330,13 +349,14 @@ final class IInputMethodManagerImpl extends IInputMethodManager.Stub { mCallback.showInputMethodPickerFromClient(client, auxiliarySubtypeMode); } - @EnforcePermission(Manifest.permission.WRITE_SECURE_SETTINGS) + @EnforcePermission(allOf = { + Manifest.permission.WRITE_SECURE_SETTINGS, + Manifest.permission.INTERACT_ACROSS_USERS_FULL}) @Override public void showInputMethodPickerFromSystem(int auxiliarySubtypeMode, int displayId) { super.showInputMethodPickerFromSystem_enforcePermission(); mCallback.showInputMethodPickerFromSystem(auxiliarySubtypeMode, displayId); - } @EnforcePermission(Manifest.permission.TEST_INPUT_METHOD) @@ -347,7 +367,9 @@ final class IInputMethodManagerImpl extends IInputMethodManager.Stub { return mCallback.isInputMethodPickerShownForTest(); } - @EnforcePermission(Manifest.permission.WRITE_SECURE_SETTINGS) + @EnforcePermission(allOf = { + Manifest.permission.WRITE_SECURE_SETTINGS, + Manifest.permission.INTERACT_ACROSS_USERS_FULL}) @Override public void onImeSwitchButtonClickFromSystem(int displayId) { super.onImeSwitchButtonClickFromSystem_enforcePermission(); @@ -382,12 +404,14 @@ final class IInputMethodManagerImpl extends IInputMethodManager.Stub { mCallback.reportPerceptibleAsync(windowToken, perceptible); } - @EnforcePermission(Manifest.permission.INTERNAL_SYSTEM_WINDOW) + @EnforcePermission(allOf = { + Manifest.permission.INTERNAL_SYSTEM_WINDOW, + Manifest.permission.INTERACT_ACROSS_USERS_FULL}) @Override - public void removeImeSurface() { + public void removeImeSurface(int displayId) { super.removeImeSurface_enforcePermission(); - mCallback.removeImeSurface(); + mCallback.removeImeSurface(displayId); } @Override diff --git a/services/core/java/com/android/server/inputmethod/ImeVisibilityStateComputer.java b/services/core/java/com/android/server/inputmethod/ImeVisibilityStateComputer.java index ae411338a4dc..42a99defcbee 100644 --- a/services/core/java/com/android/server/inputmethod/ImeVisibilityStateComputer.java +++ b/services/core/java/com/android/server/inputmethod/ImeVisibilityStateComputer.java @@ -39,6 +39,7 @@ import android.accessibilityservice.AccessibilityService; import android.annotation.AnyThread; import android.annotation.IntDef; import android.annotation.NonNull; +import android.annotation.Nullable; import android.annotation.UserIdInt; import android.content.res.Configuration; import android.os.Binder; @@ -120,14 +121,23 @@ public final class ImeVisibilityStateComputer { @GuardedBy("ImfLock.class") private boolean mRequestedImeScreenshot; - /** The window token of the current visible IME layering target overlay. */ + /** Whether there is a visible IME layering target overlay. */ @GuardedBy("ImfLock.class") - private IBinder mCurVisibleImeLayeringOverlay; + private boolean mHasVisibleImeLayeringOverlay; /** The window token of the current visible IME input target. */ @GuardedBy("ImfLock.class") private IBinder mCurVisibleImeInputTarget; + /** + * The last window token that we confirmed that IME started talking to. This is always updated + * upon reports from the input method. If the window state is already changed before the report + * is handled, this field just keeps the last value. + */ + @GuardedBy("ImfLock.class") + @Nullable + private IBinder mLastImeTargetWindow; + /** Represent the invalid IME visibility state */ public static final int STATE_INVALID = -1; @@ -208,34 +218,36 @@ public final class ImeVisibilityStateComputer { mPolicy = imePolicy; mWindowManagerInternal.setInputMethodTargetChangeListener(new ImeTargetChangeListener() { @Override - public void onImeTargetOverlayVisibilityChanged(IBinder overlayWindowToken, + public void onImeTargetOverlayVisibilityChanged(@NonNull IBinder overlayWindowToken, @WindowManager.LayoutParams.WindowType int windowType, boolean visible, boolean removed) { // Ignoring the starting window since it's ok to cover the IME target // window in temporary without affecting the IME visibility. - final var overlay = (visible && !removed && windowType != TYPE_APPLICATION_STARTING) - ? overlayWindowToken : null; + final boolean hasOverlay = visible && !removed + && windowType != TYPE_APPLICATION_STARTING; synchronized (ImfLock.class) { - mCurVisibleImeLayeringOverlay = overlay; - + mHasVisibleImeLayeringOverlay = hasOverlay; } } @Override public void onImeInputTargetVisibilityChanged(IBinder imeInputTarget, boolean visibleRequested, boolean removed) { + final boolean visibleAndNotRemoved = visibleRequested && !removed; synchronized (ImfLock.class) { - if (mCurVisibleImeInputTarget == imeInputTarget && (!visibleRequested - || removed) - && mCurVisibleImeLayeringOverlay != null) { + if (visibleAndNotRemoved) { + mCurVisibleImeInputTarget = imeInputTarget; + return; + } + if (mHasVisibleImeLayeringOverlay + && mCurVisibleImeInputTarget == imeInputTarget) { final int reason = SoftInputShowHideReason.HIDE_WHEN_INPUT_TARGET_INVISIBLE; final var statsToken = ImeTracker.forLogging().onStart(ImeTracker.TYPE_HIDE, ImeTracker.ORIGIN_SERVER, reason, false /* fromUser */); mService.onApplyImeVisibilityFromComputerLocked(imeInputTarget, statsToken, new ImeVisibilityResult(STATE_HIDE_IME_EXPLICIT, reason)); } - mCurVisibleImeInputTarget = - (visibleRequested && !removed) ? imeInputTarget : null; + mCurVisibleImeInputTarget = null; } } }); @@ -479,8 +491,7 @@ public final class ImeVisibilityStateComputer { break; case WindowManager.LayoutParams.SOFT_INPUT_STATE_UNCHANGED: // Do nothing but preserving the last IME requested visibility state. - final ImeTargetWindowState lastState = - getWindowStateOrNull(mService.mLastImeTargetWindow); + final ImeTargetWindowState lastState = getWindowStateOrNull(mLastImeTargetWindow); if (lastState != null) { state.setRequestedImeVisible(lastState.mRequestedImeVisible); } @@ -568,7 +579,6 @@ public final class ImeVisibilityStateComputer { } @GuardedBy("ImfLock.class") - @VisibleForTesting ImeVisibilityResult onInteractiveChanged(IBinder windowToken, boolean interactive) { final ImeTargetWindowState state = getWindowStateOrNull(windowToken); if (state != null && state.isRequestedImeVisible() && mInputShown && !interactive) { @@ -632,6 +642,17 @@ public final class ImeVisibilityStateComputer { } @GuardedBy("ImfLock.class") + @Nullable + IBinder getLastImeTargetWindow() { + return mLastImeTargetWindow; + } + + @GuardedBy("ImfLock.class") + void setLastImeTargetWindow(@Nullable IBinder imeTargetWindow) { + mLastImeTargetWindow = imeTargetWindow; + } + + @GuardedBy("ImfLock.class") void dumpDebug(ProtoOutputStream proto, long fieldId) { proto.write(SHOW_EXPLICITLY_REQUESTED, mRequestedShowExplicitly); proto.write(SHOW_FORCED, mShowForced); @@ -647,6 +668,7 @@ public final class ImeVisibilityStateComputer { + " mShowForced=" + mShowForced); p.println(prefix + "mImeHiddenByDisplayPolicy=" + mPolicy.isImeHiddenByDisplayPolicy()); p.println(prefix + "mInputShown=" + mInputShown); + p.println(prefix + "mLastImeTargetWindow=" + mLastImeTargetWindow); } /** diff --git a/services/core/java/com/android/server/inputmethod/ImmutableSparseArray.java b/services/core/java/com/android/server/inputmethod/ImmutableSparseArray.java new file mode 100644 index 000000000000..382aa8a9074d --- /dev/null +++ b/services/core/java/com/android/server/inputmethod/ImmutableSparseArray.java @@ -0,0 +1,183 @@ +/* + * Copyright (C) 2024 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.android.server.inputmethod; + + +import android.annotation.AnyThread; +import android.annotation.NonNull; +import android.annotation.Nullable; +import android.util.SparseArray; + +import java.util.function.Consumer; + +/** + * A holder object to expose {@link SparseArray} to multiple threads in a thread-safe manner through + * "final Field Semantics" defined in JLS 17.5, with only exposing thread-safe methods such as + * {@link SparseArray#get(int)} and {@link SparseArray#size()} from {@link SparseArray}, and with + * adding clone-with-update style methods {@link #cloneWithPutOrSelf(int, Object)} and + * {@link #cloneWithRemoveOrSelf(int)} instead of exposing mutation methods. + * + * @param <E> Type of the element + */ +final class ImmutableSparseArray<E> { + @NonNull + private final SparseArray<E> mArray; + + private static final ImmutableSparseArray<Object> EMPTY = + new ImmutableSparseArray<>(new SparseArray<>()); + + /** + * Returns an empty {@link ImmutableSparseArray} instance. + * + * @return An empty {@link ImmutableSparseArray} instance. + * @param <T> Type of the element + */ + @SuppressWarnings("unchecked") + @AnyThread + @NonNull + static <T> ImmutableSparseArray<T> empty() { + return (ImmutableSparseArray<T>) EMPTY; + } + + private ImmutableSparseArray(@NonNull SparseArray<E> array) { + mArray = array; + } + + /** + * @return the size of this array + */ + @AnyThread + int size() { + return mArray.size(); + } + + /** + * Returns the key of the specified index. + * + * @return the key of the specified index + * @throws ArrayIndexOutOfBoundsException when the index is out of range + */ + @AnyThread + int keyAt(int index) { + return mArray.keyAt(index); + } + + /** + * Returns the value of the specified index. + * + * @return the value of the specified index + * @throws ArrayIndexOutOfBoundsException when the index is out of range + */ + @AnyThread + @Nullable + public E valueAt(int index) { + return mArray.valueAt(index); + } + + /** + * Returns the index of the specified key. + * + * @return the index of the specified key if exists. Otherwise {@code -1} + */ + @AnyThread + int indexOfKey(int key) { + return mArray.indexOfKey(key); + } + + /** + * Returns {@code true} if the given {@code key} exists. + * + * @param key the key to be queried + * @return {@code true} if the given {@code key} exists + */ + @AnyThread + boolean contains(int key) { + return mArray.contains(key); + } + + /** + * Returns the value associated with the {@code key}. + * + * @param key the key to be queried + * @return the value associated with the {@code key} if exists. Otherwise {@code null} + */ + @AnyThread + @Nullable + E get(int key) { + return mArray.get(key); + } + + /** + * Run {@link Consumer} for each value. + * + * @param consumer {@link Consumer} to be called back + */ + @AnyThread + void forEach(@NonNull Consumer<E> consumer) { + final int size = mArray.size(); + for (int i = 0; i < size; ++i) { + consumer.accept(mArray.valueAt(i)); + } + } + + /** + * Returns an instance of {@link ImmutableSparseArray} that has the given key and value on top + * of items cloned from this instance. + * + * @param key the key to be added + * @param value the value to be added + * @return the same {@link ImmutableSparseArray} instance if there is actually no update. + * Otherwise, a new instance of {@link ImmutableSparseArray} + */ + @AnyThread + @NonNull + ImmutableSparseArray<E> cloneWithPutOrSelf(int key, @Nullable E value) { + final var prevKeyIndex = mArray.indexOfKey(key); + if (prevKeyIndex >= 0) { + final var prevValue = mArray.valueAt(prevKeyIndex); + if (prevValue == value) { + return this; + } + } + final var clone = mArray.clone(); + clone.put(key, value); + return new ImmutableSparseArray<>(clone); + } + + /** + * Returns an instance of {@link ImmutableSparseArray} that does not have the given key on top + * of items cloned from this instance. + * + * @param key the key to be removed + * @return the same {@link ImmutableSparseArray} instance if there is actually no update. + * Otherwise, a new instance of {@link ImmutableSparseArray} + */ + @AnyThread + @NonNull + ImmutableSparseArray<E> cloneWithRemoveOrSelf(int key) { + final int index = indexOfKey(key); + if (index < 0) { + return this; + } + if (mArray.size() == 1) { + return empty(); + } + final var clone = mArray.clone(); + clone.remove(key); + return new ImmutableSparseArray<>(clone); + } +} diff --git a/services/core/java/com/android/server/inputmethod/InputMethodBindingController.java b/services/core/java/com/android/server/inputmethod/InputMethodBindingController.java index 9837ab16a310..03cbab53f1b8 100644 --- a/services/core/java/com/android/server/inputmethod/InputMethodBindingController.java +++ b/services/core/java/com/android/server/inputmethod/InputMethodBindingController.java @@ -463,7 +463,7 @@ final class InputMethodBindingController { // should now try to restart the service for us. mLastBindTime = SystemClock.uptimeMillis(); clearCurMethodAndSessions(); - mService.clearInputShownLocked(); + mService.mVisibilityStateComputer.setInputShown(false); mService.unbindCurrentClientLocked(UnbindReason.DISCONNECT_IME, mUserId); } } diff --git a/services/core/java/com/android/server/inputmethod/InputMethodManagerInternal.java b/services/core/java/com/android/server/inputmethod/InputMethodManagerInternal.java index 13209d861e8b..dba04656e48f 100644 --- a/services/core/java/com/android/server/inputmethod/InputMethodManagerInternal.java +++ b/services/core/java/com/android/server/inputmethod/InputMethodManagerInternal.java @@ -75,13 +75,13 @@ public abstract class InputMethodManagerInternal { public abstract void setInteractive(boolean interactive); /** - * Hides the input methods for all the users, if visible. + * Hides the input method for the specified {@code originatingDisplayId}, if visible. * * @param reason the reason for hiding the current input method * @param originatingDisplayId the display ID the request is originated */ @ImfLockFree - public abstract void hideAllInputMethods(@SoftInputShowHideReason int reason, + public abstract void hideInputMethod(@SoftInputShowHideReason int reason, int originatingDisplayId); /** @@ -315,7 +315,7 @@ public abstract class InputMethodManagerInternal { @ImfLockFree @Override - public void hideAllInputMethods(@SoftInputShowHideReason int reason, + public void hideInputMethod(@SoftInputShowHideReason int reason, int originatingDisplayId) { } diff --git a/services/core/java/com/android/server/inputmethod/InputMethodManagerService.java b/services/core/java/com/android/server/inputmethod/InputMethodManagerService.java index 9d007c601b8d..084e11824fa8 100644 --- a/services/core/java/com/android/server/inputmethod/InputMethodManagerService.java +++ b/services/core/java/com/android/server/inputmethod/InputMethodManagerService.java @@ -81,6 +81,7 @@ import android.content.pm.PackageManagerInternal; import android.content.pm.ResolveInfo; import android.content.pm.ServiceInfo; import android.content.pm.UserInfo; +import android.content.res.Configuration; import android.content.res.Resources; import android.hardware.input.InputManager; import android.inputmethodservice.InputMethodService; @@ -253,12 +254,9 @@ public final class InputMethodManagerService implements IInputMethodManagerImpl. private @interface MultiUserUnawareField { } - private static final int MSG_SHOW_IM_SUBTYPE_PICKER = 1; - - private static final int MSG_HIDE_ALL_INPUT_METHODS = 1035; + private static final int MSG_HIDE_INPUT_METHOD = 1035; private static final int MSG_REMOVE_IME_SURFACE = 1060; private static final int MSG_REMOVE_IME_SURFACE_FROM_WINDOW = 1061; - private static final int MSG_UPDATE_IME_WINDOW_STATUS = 1070; private static final int MSG_RESET_HANDWRITING = 1090; private static final int MSG_START_HANDWRITING = 1100; @@ -305,6 +303,28 @@ public final class InputMethodManagerService implements IInputMethodManagerImpl. private final String[] mNonPreemptibleInputMethods; /** + * Whether the new Input Method Switcher menu is enabled. + * + * @see #shouldEnableNewInputMethodSwitcherMenu + */ + @SharedByAllUsersField + private final boolean mNewInputMethodSwitcherMenuEnabled; + + /** + * Returns {@code true} if the new Input Method Switcher menu is enabled. This will be + * {@code false} for watches and small screen devices. + * + * @param context the context to check the device configuration for. + */ + private static boolean shouldEnableNewInputMethodSwitcherMenu(@NonNull Context context) { + final boolean isWatch = context.getPackageManager() + .hasSystemFeature(PackageManager.FEATURE_WATCH); + final boolean isSmallScreen = (context.getResources().getConfiguration().screenLayout + & Configuration.SCREENLAYOUT_SIZE_MASK) == Configuration.SCREENLAYOUT_SIZE_SMALL; + return Flags.imeSwitcherRevamp() && !isWatch && !isSmallScreen; + } + + /** * See {@link #shouldEnableConcurrentMultiUserMode(Context)} about when set to be {@code true}. */ @SharedByAllUsersField @@ -339,6 +359,35 @@ public final class InputMethodManagerService implements IInputMethodManagerImpl. return mConcurrentMultiUserModeEnabled ? callingProcessUserId : mCurrentUserId; } + /** + * Figures out the target IME user ID associated with the given {@code displayId}. + * + * @param displayId the display ID to be queried about + * @return User ID to be used for this {@code displayId}. + */ + @GuardedBy("ImfLock.class") + @UserIdInt + private int resolveImeUserIdFromDisplayIdLocked(int displayId) { + return mConcurrentMultiUserModeEnabled + ? mUserManagerInternal.getUserAssignedToDisplay(displayId) : mCurrentUserId; + } + + /** + * Figures out the target IME user ID associated with the given {@code windowToken}. + * + * @param windowToken the Window token to be queried about + * @return User ID to be used for this {@code displayId}. + */ + @GuardedBy("ImfLock.class") + @UserIdInt + private int resolveImeUserIdFromWindowLocked(@NonNull IBinder windowToken) { + if (mConcurrentMultiUserModeEnabled) { + final int displayId = mWindowManagerInternal.getDisplayIdForWindow(windowToken); + return mUserManagerInternal.getUserAssignedToDisplay(displayId); + } + return mCurrentUserId; + } + final Context mContext; final Resources mRes; private final Handler mHandler; @@ -372,7 +421,7 @@ public final class InputMethodManagerService implements IInputMethodManagerImpl. @GuardedBy("ImfLock.class") @MultiUserUnawareField @NonNull - private final ImeVisibilityStateComputer mVisibilityStateComputer; + final ImeVisibilityStateComputer mVisibilityStateComputer; @GuardedBy("ImfLock.class") @SharedByAllUsersField @@ -423,6 +472,9 @@ public final class InputMethodManagerService implements IInputMethodManagerImpl. IInputMethodSession mSession; InputChannel mChannel; + @UserIdInt + final int mUserId; + @Override public String toString() { return "SessionState{uid=" + mClient.mUid + " pid=" + mClient.mPid @@ -431,15 +483,17 @@ public final class InputMethodManagerService implements IInputMethodManagerImpl. + " session=" + Integer.toHexString( System.identityHashCode(mSession)) + " channel=" + mChannel + + " userId=" + mUserId + "}"; } SessionState(ClientState client, IInputMethodInvoker method, - IInputMethodSession session, InputChannel channel) { + IInputMethodSession session, InputChannel channel, @UserIdInt int userId) { mClient = client; mMethod = method; mSession = session; mChannel = channel; + mUserId = userId; } } @@ -495,14 +549,6 @@ public final class InputMethodManagerService implements IInputMethodManagerImpl. } /** - * The last window token that we confirmed that IME started talking to. This is always updated - * upon reports from the input method. If the window state is already changed before the report - * is handled, this field just keeps the last value. - */ - @MultiUserUnawareField - IBinder mLastImeTargetWindow; - - /** * Map of window perceptible states indexed by their associated window tokens. * * The value {@code true} indicates that IME has not been mostly hidden via @@ -571,7 +617,7 @@ public final class InputMethodManagerService implements IInputMethodManagerImpl. private void onSecureSettingsChangedLocked(@NonNull String key, @UserIdInt int userId) { switch (key) { case Settings.Secure.SHOW_IME_WITH_HARD_KEYBOARD: { - if (!Flags.imeSwitcherRevamp()) { + if (!mNewInputMethodSwitcherMenuEnabled) { if (userId == mCurrentUserId) { mMenuController.updateKeyboardFromSettingsLocked(); } @@ -640,7 +686,7 @@ public final class InputMethodManagerService implements IInputMethodManagerImpl. } } } - if (Flags.imeSwitcherRevamp()) { + if (mNewInputMethodSwitcherMenuEnabled) { synchronized (ImfLock.class) { final var bindingController = getInputMethodBindingController(senderUserId); mMenuControllerNew.hide(bindingController.getCurTokenDisplayId(), @@ -944,15 +990,13 @@ public final class InputMethodManagerService implements IInputMethodManagerImpl. // TODO(b/196206770): Disallow I/O on this thread. Currently it's needed for loading // additional subtypes in switchUserOnHandlerLocked(). final ServiceThread thread = new ServiceThread(HANDLER_THREAD_NAME, - Process.THREAD_PRIORITY_FOREGROUND, true /* allowIo */); + Process.THREAD_PRIORITY_FOREGROUND, false /* allowIo */); thread.start(); final ServiceThread ioThread = new ServiceThread(PACKAGE_MONITOR_THREAD_NAME, Process.THREAD_PRIORITY_FOREGROUND, true /* allowIo */); ioThread.start(); - SecureSettingsWrapper.setContentResolver(context.getContentResolver()); - return new InputMethodManagerService(context, shouldEnableConcurrentMultiUserMode(context), thread.getLooper(), Handler.createAsync(ioThread.getLooper()), @@ -1011,7 +1055,6 @@ public final class InputMethodManagerService implements IInputMethodManagerImpl. public void onUserRemoved(UserInfo user) { // Called directly from UserManagerService. Do not block the calling thread. final int userId = user.id; - SecureSettingsWrapper.onUserRemoved(userId); AdditionalSubtypeMapRepository.remove(userId); InputMethodSettingsRepository.remove(userId); mService.mUserDataRepository.remove(userId); @@ -1063,8 +1106,8 @@ public final class InputMethodManagerService implements IInputMethodManagerImpl. for (int userId : userIds) { Slog.d(TAG, "Start initialization for user=" + userId); - final var additionalSubtypeMap = - AdditionalSubtypeMapRepository.ensureInitializedAndGet(userId); + AdditionalSubtypeMapRepository.initializeIfNecessary(userId); + final var additionalSubtypeMap = AdditionalSubtypeMapRepository.get(userId); final var settings = InputMethodManagerService.queryInputMethodServicesInternal( context, userId, additionalSubtypeMap, DirectBootAwareness.AUTO).getMethodMap(); @@ -1083,6 +1126,21 @@ public final class InputMethodManagerService implements IInputMethodManagerImpl. } }); } + + @Override + public void onUserStopped(@NonNull TargetUser user) { + final int userId = user.getUserIdentifier(); + // Called on ActivityManager thread. + SecureSettingsWrapper.onUserStopped(userId); + mService.mIoHandler.post(() -> { + final var additionalSubtypeMap = AdditionalSubtypeMapRepository.get(userId); + final var settings = InputMethodManagerService.queryInputMethodServicesInternal( + mService.mContext, userId, additionalSubtypeMap, + DirectBootAwareness.AUTO).getMethodMap(); + InputMethodSettingsRepository.put(userId, + InputMethodSettings.create(settings, userId)); + }); + } } @GuardedBy("ImfLock.class") @@ -1117,6 +1175,7 @@ public final class InputMethodManagerService implements IInputMethodManagerImpl. mConcurrentMultiUserModeEnabled = concurrentMultiUserModeEnabled; mContext = context; mRes = context.getResources(); + SecureSettingsWrapper.onStart(mContext); mHandler = Handler.createAsync(uiLooper, this); mIoHandler = ioHandler; @@ -1131,6 +1190,7 @@ public final class InputMethodManagerService implements IInputMethodManagerImpl. mUserManagerInternal = LocalServices.getService(UserManagerInternal.class); mSlotIme = mContext.getString(com.android.internal.R.string.status_bar_ime); + mNewInputMethodSwitcherMenuEnabled = shouldEnableNewInputMethodSwitcherMenu(mContext); mShowOngoingImeSwitcherForPhones = false; @@ -1143,7 +1203,7 @@ public final class InputMethodManagerService implements IInputMethodManagerImpl. : bindingControllerFactory); mMenuController = new InputMethodMenuController(this); - mMenuControllerNew = Flags.imeSwitcherRevamp() + mMenuControllerNew = mNewInputMethodSwitcherMenuEnabled ? new InputMethodMenuControllerNew() : null; mVisibilityStateComputer = new ImeVisibilityStateComputer(this); mVisibilityApplier = new DefaultImeVisibilityApplier(this); @@ -1764,7 +1824,7 @@ public final class InputMethodManagerService implements IInputMethodManagerImpl. ImeTracker.PHASE_SERVER_WAIT_IME); userData.mCurStatsToken = null; // TODO: Make mMenuController multi-user aware - if (Flags.imeSwitcherRevamp()) { + if (mNewInputMethodSwitcherMenuEnabled) { mMenuControllerNew.hide(bindingController.getCurTokenDisplayId(), userId); } else { mMenuController.hideInputMethodMenuLocked(); @@ -1799,23 +1859,6 @@ public final class InputMethodManagerService implements IInputMethodManagerImpl. } } - @VisibleForTesting - void setAttachedClientForTesting(@NonNull ClientState cs) { - synchronized (ImfLock.class) { - getUserData(mCurrentUserId).mCurClient = cs; - } - } - - @GuardedBy("ImfLock.class") - void clearInputShownLocked() { - mVisibilityStateComputer.setInputShown(false); - } - - @GuardedBy("ImfLock.class") - private boolean isInputShownLocked() { - return mVisibilityStateComputer.isInputShown(); - } - @GuardedBy("ImfLock.class") private boolean isShowRequestedForCurrentWindow(@UserIdInt int userId) { final var userData = getUserData(userId); @@ -2315,7 +2358,7 @@ public final class InputMethodManagerService implements IInputMethodManagerImpl. if (userData.mCurClient != null) { clearClientSessionLocked(userData.mCurClient); userData.mCurClient.mCurSession = new SessionState( - userData.mCurClient, method, session, channel); + userData.mCurClient, method, session, channel, userId); InputBindResult res = attachNewInputLocked( StartInputReason.SESSION_CREATED_BY_IME, true, userId); attachNewAccessibilityLocked(StartInputReason.SESSION_CREATED_BY_IME, true, @@ -2456,9 +2499,7 @@ public final class InputMethodManagerService implements IInputMethodManagerImpl. sessionState.mSession.finishSession(); } catch (RemoteException e) { Slog.w(TAG, "Session failed to close due to remote exception", e); - // TODO(b/350386877): Propagate userId from the caller or infer it from - // sessionState - final int userId = mCurrentUserId; + final int userId = sessionState.mUserId; final var bindingController = getInputMethodBindingController(userId); updateSystemUiLocked(0 /* vis */, bindingController.getBackDisposition(), userId); @@ -2589,7 +2630,7 @@ public final class InputMethodManagerService implements IInputMethodManagerImpl. if (!mShowOngoingImeSwitcherForPhones) return false; // When the IME switcher dialog is shown, the IME switcher button should be hidden. // TODO(b/305849394): Make mMenuController multi-user aware. - final boolean switcherMenuShowing = Flags.imeSwitcherRevamp() + final boolean switcherMenuShowing = mNewInputMethodSwitcherMenuEnabled ? mMenuControllerNew.isShowing() : mMenuController.getSwitchingDialogLocked() != null; if (switcherMenuShowing) { @@ -2609,7 +2650,8 @@ public final class InputMethodManagerService implements IInputMethodManagerImpl. || (visibility & InputMethodService.IME_INVISIBLE) != 0) { return false; } - if (mWindowManagerInternal.isHardKeyboardAvailable() && !Flags.imeSwitcherRevamp()) { + if (mWindowManagerInternal.isHardKeyboardAvailable() + && !mNewInputMethodSwitcherMenuEnabled) { // When physical keyboard is attached, we show the ime switcher (or notification if // NavBar is not available) because SHOW_IME_WITH_HARD_KEYBOARD settings currently // exists in the IME switcher dialog. Might be OK to remove this condition once @@ -2620,7 +2662,7 @@ public final class InputMethodManagerService implements IInputMethodManagerImpl. } final InputMethodSettings settings = InputMethodSettingsRepository.get(userId); - if (Flags.imeSwitcherRevamp()) { + if (mNewInputMethodSwitcherMenuEnabled) { // The IME switcher button should be shown when the current IME specified a // language settings activity. final var curImi = settings.getMethodMap().get(settings.getSelectedInputMethod()); @@ -2739,20 +2781,18 @@ public final class InputMethodManagerService implements IInputMethodManagerImpl. if (targetWindow != null) { mWindowManagerInternal.updateInputMethodTargetWindow(token, targetWindow); } - mLastImeTargetWindow = targetWindow; + mVisibilityStateComputer.setLastImeTargetWindow(targetWindow); } } - private void updateImeWindowStatus(boolean disableImeIcon) { - synchronized (ImfLock.class) { - // TODO(b/350386877): Propagate userId from the caller. - final int userId = mCurrentUserId; - if (disableImeIcon) { - final var bindingController = getInputMethodBindingController(userId); - updateSystemUiLocked(0, bindingController.getBackDisposition(), userId); - } else { - updateSystemUiLocked(userId); - } + @GuardedBy("ImfLock.class") + private void updateImeWindowStatusLocked(boolean disableImeIcon, int displayId) { + final int userId = resolveImeUserIdFromDisplayIdLocked(displayId); + if (disableImeIcon) { + final var bindingController = getInputMethodBindingController(userId); + updateSystemUiLocked(0, bindingController.getBackDisposition(), userId); + } else { + updateSystemUiLocked(userId); } } @@ -2798,7 +2838,7 @@ public final class InputMethodManagerService implements IInputMethodManagerImpl. } final var curId = bindingController.getCurId(); // TODO(b/305849394): Make mMenuController multi-user aware. - final boolean switcherMenuShowing = Flags.imeSwitcherRevamp() + final boolean switcherMenuShowing = mNewInputMethodSwitcherMenuEnabled ? mMenuControllerNew.isShowing() : mMenuController.getSwitchingDialogLocked() != null; if (switcherMenuShowing @@ -2820,7 +2860,7 @@ public final class InputMethodManagerService implements IInputMethodManagerImpl. @GuardedBy("ImfLock.class") void updateFromSettingsLocked(boolean enabledMayChange, @UserIdInt int userId) { updateInputMethodsFromSettingsLocked(enabledMayChange, userId); - if (!Flags.imeSwitcherRevamp()) { + if (!mNewInputMethodSwitcherMenuEnabled) { mMenuController.updateKeyboardFromSettingsLocked(); } } @@ -3005,6 +3045,9 @@ public final class InputMethodManagerService implements IInputMethodManagerImpl. @GuardedBy("ImfLock.class") private void sendResultReceiverFailureLocked(@Nullable ResultReceiver resultReceiver) { + if (resultReceiver == null) { + return; + } final boolean isInputShown = mVisibilityStateComputer.isInputShown(); resultReceiver.send(isInputShown ? InputMethodManager.RESULT_UNCHANGED_SHOWN @@ -3051,7 +3094,7 @@ public final class InputMethodManagerService implements IInputMethodManagerImpl. try { if (DEBUG) Slog.v(TAG, "Client requesting input be shown"); if (Flags.refactorInsetsController()) { - boolean wasVisible = isInputShownLocked(); + boolean wasVisible = mVisibilityStateComputer.isInputShown(); if (userData.mImeBindingState != null && userData.mImeBindingState.mFocusedWindowClient != null && userData.mImeBindingState.mFocusedWindowClient.mClient != null) { @@ -3081,8 +3124,7 @@ public final class InputMethodManagerService implements IInputMethodManagerImpl. ImeTracing.getInstance().triggerManagerServiceDump( "InputMethodManagerService#showSoftInput", mDumper); synchronized (ImfLock.class) { - // TODO(b/305849394): Infer userId from windowToken - final int userId = mCurrentUserId; + final int userId = resolveImeUserIdFromWindowLocked(windowToken); final long ident = Binder.clearCallingIdentity(); try { if (DEBUG) Slog.v(TAG, "Client requesting input be shown"); @@ -3102,8 +3144,7 @@ public final class InputMethodManagerService implements IInputMethodManagerImpl. ImeTracing.getInstance().triggerManagerServiceDump( "InputMethodManagerService#hideSoftInput", mDumper); synchronized (ImfLock.class) { - // TODO(b/305849394): Infer userId from windowToken - final int userId = mCurrentUserId; + final int userId = resolveImeUserIdFromWindowLocked(windowToken); final long ident = Binder.clearCallingIdentity(); try { if (DEBUG) Slog.v(TAG, "Client requesting input be hidden"); @@ -3365,14 +3406,14 @@ public final class InputMethodManagerService implements IInputMethodManagerImpl. Objects.requireNonNull(windowToken, "windowToken must not be null"); synchronized (ImfLock.class) { Boolean windowPerceptible = mFocusedWindowPerceptible.get(windowToken); - final int userId = mCurrentUserId; + final int userId = resolveImeUserIdFromWindowLocked(windowToken); final var userData = getUserData(userId); if (userData.mImeBindingState.mFocusedWindow != windowToken || (windowPerceptible != null && windowPerceptible == perceptible)) { return; } mFocusedWindowPerceptible.put(windowToken, windowPerceptible); - updateSystemUiLocked(mCurrentUserId); + updateSystemUiLocked(userId); } }); } @@ -3488,7 +3529,7 @@ public final class InputMethodManagerService implements IInputMethodManagerImpl. final int callingUserId = UserHandle.getUserId(uid); final int userId = resolveImeUserIdLocked(callingUserId); if (!canInteractWithImeLocked(uid, client, "hideSoftInput", statsToken, userId)) { - if (isInputShownLocked()) { + if (mVisibilityStateComputer.isInputShown()) { ImeTracker.forLogging().onFailed( statsToken, ImeTracker.PHASE_SERVER_CLIENT_FOCUSED); } else { @@ -3506,7 +3547,7 @@ public final class InputMethodManagerService implements IInputMethodManagerImpl. if (userData.mImeBindingState != null && userData.mImeBindingState.mFocusedWindowClient != null && userData.mImeBindingState.mFocusedWindowClient.mClient != null) { - boolean wasVisible = isInputShownLocked(); + boolean wasVisible = mVisibilityStateComputer.isInputShown(); // TODO add windowToken to interface userData.mImeBindingState.mFocusedWindowClient.mClient .setImeVisibility(false, statsToken); @@ -3568,7 +3609,7 @@ public final class InputMethodManagerService implements IInputMethodManagerImpl. // TODO(b/246309664): Clean up IMMS#mImeWindowVis IInputMethodInvoker curMethod = bindingController.getCurMethod(); final boolean shouldHideSoftInput = curMethod != null - && (isInputShownLocked() + && (mVisibilityStateComputer.isInputShown() || (bindingController.getImeWindowVis() & InputMethodService.IME_ACTIVE) != 0); mVisibilityStateComputer.requestImeVisibility(windowToken, false); @@ -3916,10 +3957,9 @@ public final class InputMethodManagerService implements IInputMethodManagerImpl. } @GuardedBy("ImfLock.class") - private boolean canShowInputMethodPickerLocked(IInputMethodClient client) { + private boolean canShowInputMethodPickerLocked(IInputMethodClient client, + @UserIdInt int userId) { final int uid = Binder.getCallingUid(); - // TODO(b/305849394): Get userId from callers. - final int userId = mCurrentUserId; final var userData = getUserData(userId); if (userData.mImeBindingState.mFocusedWindowClient != null && client != null && userData.mImeBindingState.mFocusedWindowClient.mClient.asBinder() @@ -3946,29 +3986,38 @@ public final class InputMethodManagerService implements IInputMethodManagerImpl. } final int callingUserId = UserHandle.getCallingUserId(); synchronized (ImfLock.class) { - if (!canShowInputMethodPickerLocked(client)) { + final int userId = resolveImeUserIdLocked(callingUserId); + if (!canShowInputMethodPickerLocked(client, userId)) { Slog.w(TAG, "Ignoring showInputMethodPickerFromClient of uid " + Binder.getCallingUid() + ": " + client); return; } - final int userId = resolveImeUserIdLocked(callingUserId); final var userData = getUserData(userId); // Always call subtype picker, because subtype picker is a superset of input method // picker. final int displayId = (userData.mCurClient != null) ? userData.mCurClient.mSelfReportedDisplayId : DEFAULT_DISPLAY; - mHandler.obtainMessage(MSG_SHOW_IM_SUBTYPE_PICKER, auxiliarySubtypeMode, displayId) - .sendToTarget(); + mHandler.post(() -> { + synchronized (ImfLock.class) { + showInputMethodPickerLocked(auxiliarySubtypeMode, displayId, userId); + } + }); } } - @IInputMethodManagerImpl.PermissionVerified(Manifest.permission.WRITE_SECURE_SETTINGS) + @IInputMethodManagerImpl.PermissionVerified(allOf = { + Manifest.permission.INTERACT_ACROSS_USERS_FULL, + Manifest.permission.WRITE_SECURE_SETTINGS}) @Override public void showInputMethodPickerFromSystem(int auxiliarySubtypeMode, int displayId) { // Always call subtype picker, because subtype picker is a superset of input method // picker. - mHandler.obtainMessage(MSG_SHOW_IM_SUBTYPE_PICKER, auxiliarySubtypeMode, displayId) - .sendToTarget(); + mHandler.post(() -> { + synchronized (ImfLock.class) { + final int userId = resolveImeUserIdFromDisplayIdLocked(displayId); + showInputMethodPickerLocked(auxiliarySubtypeMode, displayId, userId); + } + }); } /** @@ -3977,7 +4026,7 @@ public final class InputMethodManagerService implements IInputMethodManagerImpl. @IInputMethodManagerImpl.PermissionVerified(Manifest.permission.TEST_INPUT_METHOD) public boolean isInputMethodPickerShownForTest() { synchronized (ImfLock.class) { - return Flags.imeSwitcherRevamp() + return mNewInputMethodSwitcherMenuEnabled ? mMenuControllerNew.isShowing() : mMenuController.isisInputMethodPickerShownForTestLocked(); } @@ -4052,11 +4101,13 @@ public final class InputMethodManagerService implements IInputMethodManagerImpl. } } - @IInputMethodManagerImpl.PermissionVerified(Manifest.permission.WRITE_SECURE_SETTINGS) + @IInputMethodManagerImpl.PermissionVerified(allOf = { + Manifest.permission.INTERACT_ACROSS_USERS_FULL, + Manifest.permission.WRITE_SECURE_SETTINGS}) @Override public void onImeSwitchButtonClickFromSystem(int displayId) { synchronized (ImfLock.class) { - final int userId = mCurrentUserId; + final int userId = resolveImeUserIdFromDisplayIdLocked(displayId); final var userData = getUserData(userId); final var bindingController = userData.mBindingController; final var curToken = bindingController.getCurToken(); @@ -4394,9 +4445,11 @@ public final class InputMethodManagerService implements IInputMethodManagerImpl. }); } - @IInputMethodManagerImpl.PermissionVerified(Manifest.permission.INTERNAL_SYSTEM_WINDOW) + @IInputMethodManagerImpl.PermissionVerified(allOf = { + Manifest.permission.INTERACT_ACROSS_USERS_FULL, + Manifest.permission.INTERNAL_SYSTEM_WINDOW}) @Override - public void removeImeSurface() { + public void removeImeSurface(int displayId) { mHandler.obtainMessage(MSG_REMOVE_IME_SURFACE).sendToTarget(); } @@ -4665,8 +4718,8 @@ public final class InputMethodManagerService implements IInputMethodManagerImpl. proto.write(CUR_SEQ, bindingController.getSequenceNumber()); proto.write(CUR_CLIENT, Objects.toString(userData.mCurClient)); userData.mImeBindingState.dumpDebug(proto, mWindowManagerInternal); - proto.write(LAST_IME_TARGET_WINDOW_NAME, - mWindowManagerInternal.getWindowName(mLastImeTargetWindow)); + proto.write(LAST_IME_TARGET_WINDOW_NAME, mWindowManagerInternal.getWindowName( + mVisibilityStateComputer.getLastImeTargetWindow())); proto.write(CUR_FOCUSED_WINDOW_SOFT_INPUT_MODE, InputMethodDebug.softInputModeToString( userData.mImeBindingState.mFocusedWindowSoftInputMode)); if (userData.mCurEditorInfo != null) { @@ -4683,7 +4736,7 @@ public final class InputMethodManagerService implements IInputMethodManagerImpl. proto.write(IS_INTERACTIVE, mIsInteractive); proto.write(BACK_DISPOSITION, bindingController.getBackDisposition()); proto.write(IME_WINDOW_VISIBILITY, bindingController.getImeWindowVis()); - if (!Flags.imeSwitcherRevamp()) { + if (!mNewInputMethodSwitcherMenuEnabled) { proto.write(SHOW_IME_WITH_HARD_KEYBOARD, mMenuController.getShowImeWithHardKeyboard()); } @@ -4840,8 +4893,8 @@ public final class InputMethodManagerService implements IInputMethodManagerImpl. .setImeVisibility(false, statsToken); } } else { - hideCurrentInputLocked(mLastImeTargetWindow, statsToken, flags, - null /* resultReceiver */, reason, userId); + hideCurrentInputLocked(mVisibilityStateComputer.getLastImeTargetWindow(), + statsToken, flags, null /* resultReceiver */, reason, userId); } } finally { Binder.restoreCallingIdentity(ident); @@ -4879,9 +4932,9 @@ public final class InputMethodManagerService implements IInputMethodManagerImpl. .setImeVisibility(true, statsToken); } } else { - showCurrentInputLocked(mLastImeTargetWindow, statsToken, flags, - MotionEvent.TOOL_TYPE_UNKNOWN, null /* resultReceiver */, reason, - userId); + showCurrentInputLocked(mVisibilityStateComputer.getLastImeTargetWindow(), + statsToken, flags, MotionEvent.TOOL_TYPE_UNKNOWN, + null /* resultReceiver */, reason, userId); } } finally { Binder.restoreCallingIdentity(ident); @@ -4901,8 +4954,7 @@ public final class InputMethodManagerService implements IInputMethodManagerImpl. @GuardedBy("ImfLock.class") void onApplyImeVisibilityFromComputerLocked(IBinder windowToken, @NonNull ImeTracker.Token statsToken, @NonNull ImeVisibilityResult result) { - // TODO(b/305849394): Infer userId from windowToken - final int userId = mCurrentUserId; + final int userId = resolveImeUserIdFromWindowLocked(windowToken); mVisibilityApplier.applyImeVisibility(windowToken, statsToken, result.getState(), result.getReason(), userId); } @@ -4960,89 +5012,80 @@ public final class InputMethodManagerService implements IInputMethodManagerImpl. userData.mEnabledAccessibilitySessions = accessibilitySessions; } - @SuppressWarnings("unchecked") - @UiThread - @Override - public boolean handleMessage(Message msg) { - switch (msg.what) { - case MSG_SHOW_IM_SUBTYPE_PICKER: - final boolean showAuxSubtypes; - final int displayId = msg.arg2; - switch (msg.arg1) { - case InputMethodManager.SHOW_IM_PICKER_MODE_AUTO: - // This is undocumented so far, but IMM#showInputMethodPicker() has been - // implemented so that auxiliary subtypes will be excluded when the soft - // keyboard is invisible. - synchronized (ImfLock.class) { - showAuxSubtypes = isInputShownLocked(); - } - break; - case InputMethodManager.SHOW_IM_PICKER_MODE_INCLUDE_AUXILIARY_SUBTYPES: - showAuxSubtypes = true; - break; - case InputMethodManager.SHOW_IM_PICKER_MODE_EXCLUDE_AUXILIARY_SUBTYPES: - showAuxSubtypes = false; - break; - default: - Slog.e(TAG, "Unknown subtype picker mode = " + msg.arg1); - return false; - } - synchronized (ImfLock.class) { - final InputMethodSettings settings = - InputMethodSettingsRepository.get(mCurrentUserId); - final int userId = settings.getUserId(); - final boolean isScreenLocked = mWindowManagerInternal.isKeyguardLocked() - && mWindowManagerInternal.isKeyguardSecure(userId); - final String lastInputMethodId = settings.getSelectedInputMethod(); - int lastInputMethodSubtypeId = - settings.getSelectedInputMethodSubtypeId(lastInputMethodId); - - final List<ImeSubtypeListItem> imList = InputMethodSubtypeSwitchingController - .getSortedInputMethodAndSubtypeList( - showAuxSubtypes, isScreenLocked, true /* forImeMenu */, - mContext, settings); - if (imList.isEmpty()) { - Slog.w(TAG, "Show switching menu failed, imList is empty," - + " showAuxSubtypes: " + showAuxSubtypes - + " isScreenLocked: " + isScreenLocked - + " userId: " + userId); - return false; - } - - if (Flags.imeSwitcherRevamp()) { - if (DEBUG) { - Slog.v(TAG, "Show IME switcher menu," - + " showAuxSubtypes=" + showAuxSubtypes - + " displayId=" + displayId - + " preferredInputMethodId=" + lastInputMethodId - + " preferredInputMethodSubtypeId=" + lastInputMethodSubtypeId); - } + @GuardedBy("ImfLock.class") + private void showInputMethodPickerLocked(int auxiliarySubtypeMode, int displayId, + @UserIdInt int userId) { + final boolean showAuxSubtypes; + switch (auxiliarySubtypeMode) { + // This is undocumented so far, but IMM#showInputMethodPicker() has been + // implemented so that auxiliary subtypes will be excluded when the soft + // keyboard is invisible. + case InputMethodManager.SHOW_IM_PICKER_MODE_AUTO -> + showAuxSubtypes = mVisibilityStateComputer.isInputShown(); + case InputMethodManager.SHOW_IM_PICKER_MODE_INCLUDE_AUXILIARY_SUBTYPES -> + showAuxSubtypes = true; + case InputMethodManager.SHOW_IM_PICKER_MODE_EXCLUDE_AUXILIARY_SUBTYPES -> + showAuxSubtypes = false; + default -> { + Slog.e(TAG, "Unknown subtype picker mode=" + auxiliarySubtypeMode); + return; + } + } + final InputMethodSettings settings = InputMethodSettingsRepository.get(userId); + final boolean isScreenLocked = mWindowManagerInternal.isKeyguardLocked() + && mWindowManagerInternal.isKeyguardSecure(userId); + final String lastInputMethodId = settings.getSelectedInputMethod(); + int lastInputMethodSubtypeId = settings.getSelectedInputMethodSubtypeId(lastInputMethodId); + + final List<ImeSubtypeListItem> imList = InputMethodSubtypeSwitchingController + .getSortedInputMethodAndSubtypeList( + showAuxSubtypes, isScreenLocked, true /* forImeMenu */, + mContext, settings); + if (imList.isEmpty()) { + Slog.w(TAG, "Show switching menu failed, imList is empty," + + " showAuxSubtypes: " + showAuxSubtypes + + " isScreenLocked: " + isScreenLocked + + " userId: " + userId); + return; + } - final var itemsAndIndex = getInputMethodPickerItems(imList, - lastInputMethodId, lastInputMethodSubtypeId, userId); - final var menuItems = itemsAndIndex.first; - final int selectedIndex = itemsAndIndex.second; + if (mNewInputMethodSwitcherMenuEnabled) { + if (DEBUG) { + Slog.v(TAG, "Show IME switcher menu," + + " showAuxSubtypes=" + showAuxSubtypes + + " displayId=" + displayId + + " preferredInputMethodId=" + lastInputMethodId + + " preferredInputMethodSubtypeId=" + lastInputMethodSubtypeId); + } - if (selectedIndex == -1) { - Slog.w(TAG, "Switching menu shown with no item selected" - + ", IME id: " + lastInputMethodId - + ", subtype index: " + lastInputMethodSubtypeId); - } + final var itemsAndIndex = getInputMethodPickerItems(imList, + lastInputMethodId, lastInputMethodSubtypeId, userId); + final var menuItems = itemsAndIndex.first; + final int selectedIndex = itemsAndIndex.second; - mMenuControllerNew.show(menuItems, selectedIndex, displayId, userId); - } else { - mMenuController.showInputMethodMenuLocked(showAuxSubtypes, displayId, - lastInputMethodId, lastInputMethodSubtypeId, imList); - } - } - return true; + if (selectedIndex == -1) { + Slog.w(TAG, "Switching menu shown with no item selected" + + ", IME id: " + lastInputMethodId + + ", subtype index: " + lastInputMethodSubtypeId); + } - // --------------------------------------------------------- + mMenuControllerNew.show(menuItems, selectedIndex, displayId, userId); + } else { + mMenuController.showInputMethodMenuLocked(showAuxSubtypes, displayId, + lastInputMethodId, lastInputMethodSubtypeId, imList); + } + } - case MSG_HIDE_ALL_INPUT_METHODS: + @SuppressWarnings("unchecked") + @UiThread + @Override + public boolean handleMessage(Message msg) { + switch (msg.what) { + case MSG_HIDE_INPUT_METHOD: { + @SoftInputShowHideReason final int reason = msg.arg1; + final int originatingDisplayId = msg.arg2; synchronized (ImfLock.class) { - // TODO(b/305849394): Needs to figure out what to do where for background users. - final int userId = mCurrentUserId; + final int userId = resolveImeUserIdFromDisplayIdLocked(originatingDisplayId); final var userData = getUserData(userId); if (Flags.refactorInsetsController()) { if (userData.mImeBindingState != null @@ -5050,15 +5093,16 @@ public final class InputMethodManagerService implements IInputMethodManagerImpl. && userData.mImeBindingState.mFocusedWindowClient.mClient != null) { userData.mImeBindingState.mFocusedWindowClient.mClient .setImeVisibility(false, - null /* TODO(b329229469) check statsToken */); + null /* TODO(b329229469) check statsToken */); } } else { - @SoftInputShowHideReason final int reason = (int) msg.obj; + hideCurrentInputLocked(userData.mImeBindingState.mFocusedWindow, 0 /* flags */, reason, userId); } } return true; + } case MSG_REMOVE_IME_SURFACE: { synchronized (ImfLock.class) { // TODO(b/305849394): Needs to figure out what to do where for background users. @@ -5078,8 +5122,7 @@ public final class InputMethodManagerService implements IInputMethodManagerImpl. case MSG_REMOVE_IME_SURFACE_FROM_WINDOW: { IBinder windowToken = (IBinder) msg.obj; synchronized (ImfLock.class) { - // TODO(b/305849394): Infer userId from windowToken. - final int userId = mCurrentUserId; + final int userId = resolveImeUserIdFromWindowLocked(windowToken); final var userData = getUserData(userId); try { if (windowToken == userData.mImeBindingState.mFocusedWindow @@ -5092,10 +5135,6 @@ public final class InputMethodManagerService implements IInputMethodManagerImpl. } return true; } - case MSG_UPDATE_IME_WINDOW_STATUS: { - updateImeWindowStatus(msg.arg1 == 1); - return true; - } // --------------------------------------------------------- @@ -5105,7 +5144,7 @@ public final class InputMethodManagerService implements IInputMethodManagerImpl. // -------------------------------------------------------------- case MSG_HARD_KEYBOARD_SWITCH_CHANGED: - if (!Flags.imeSwitcherRevamp()) { + if (!mNewInputMethodSwitcherMenuEnabled) { mMenuController.handleHardKeyboardStatusChange(msg.arg1 == 1); } synchronized (ImfLock.class) { @@ -5778,10 +5817,11 @@ public final class InputMethodManagerService implements IInputMethodManagerImpl. @ImfLockFree @Override - public void hideAllInputMethods(@SoftInputShowHideReason int reason, + public void hideInputMethod(@SoftInputShowHideReason int reason, int originatingDisplayId) { - mHandler.removeMessages(MSG_HIDE_ALL_INPUT_METHODS); - mHandler.obtainMessage(MSG_HIDE_ALL_INPUT_METHODS, reason).sendToTarget(); + mHandler.removeMessages(MSG_HIDE_INPUT_METHOD); + mHandler.obtainMessage(MSG_HIDE_INPUT_METHOD, reason, originatingDisplayId) + .sendToTarget(); } @ImfLockFree @@ -5883,8 +5923,7 @@ public final class InputMethodManagerService implements IInputMethodManagerImpl. @Override public void reportImeControl(@Nullable IBinder windowToken) { synchronized (ImfLock.class) { - // TODO(b/305849394): Need to infer userId or get userId from callers. - final int userId = mCurrentUserId; + final int userId = resolveImeUserIdFromWindowLocked(windowToken); final var userData = getUserData(userId); if (userData.mImeBindingState.mFocusedWindow != windowToken) { // A perceptible value was set for the focused window, but it is no longer in @@ -5899,14 +5938,14 @@ public final class InputMethodManagerService implements IInputMethodManagerImpl. @Override public void onImeParentChanged(int displayId) { synchronized (ImfLock.class) { - // TODO(b/305849394): Need to infer userId or get userId from callers. - final int userId = mCurrentUserId; + final int userId = resolveImeUserIdFromDisplayIdLocked(displayId); final var userData = getUserData(userId); // Hide the IME method menu only when the IME surface parent is changed by the // input target changed, in case seeing the dialog dismiss flickering during // the next focused window starting the input connection. - if (mLastImeTargetWindow != userData.mImeBindingState.mFocusedWindow) { - if (Flags.imeSwitcherRevamp()) { + if (mVisibilityStateComputer.getLastImeTargetWindow() + != userData.mImeBindingState.mFocusedWindow) { + if (mNewInputMethodSwitcherMenuEnabled) { final var bindingController = getInputMethodBindingController(userId); mMenuControllerNew.hide(bindingController.getCurTokenDisplayId(), userId); } else { @@ -5925,8 +5964,11 @@ public final class InputMethodManagerService implements IInputMethodManagerImpl. @ImfLockFree @Override public void updateImeWindowStatus(boolean disableImeIcon, int displayId) { - mHandler.obtainMessage(MSG_UPDATE_IME_WINDOW_STATUS, disableImeIcon ? 1 : 0, 0) - .sendToTarget(); + mHandler.post(() -> { + synchronized (ImfLock.class) { + updateImeWindowStatusLocked(disableImeIcon, displayId); + } + }); } @Override @@ -6024,8 +6066,8 @@ public final class InputMethodManagerService implements IInputMethodManagerImpl. public void onSwitchKeyboardLayoutShortcut(int direction, int displayId, IBinder targetWindowToken) { synchronized (ImfLock.class) { - // TODO(b/305849394): Infer userId from displayId - switchKeyboardLayoutLocked(direction, getUserData(mCurrentUserId)); + final int userId = resolveImeUserIdFromDisplayIdLocked(displayId); + switchKeyboardLayoutLocked(direction, getUserData(userId)); } } } @@ -6259,7 +6301,7 @@ public final class InputMethodManagerService implements IInputMethodManagerImpl. }; mUserDataRepository.forAllUserData(userDataDump); - if (Flags.imeSwitcherRevamp()) { + if (mNewInputMethodSwitcherMenuEnabled) { p.println(" menuControllerNew:"); mMenuControllerNew.dump(p, " "); } else { diff --git a/services/core/java/com/android/server/inputmethod/InputMethodSettingsRepository.java b/services/core/java/com/android/server/inputmethod/InputMethodSettingsRepository.java index 1b840362a8cf..4f5af6376ab0 100644 --- a/services/core/java/com/android/server/inputmethod/InputMethodSettingsRepository.java +++ b/services/core/java/com/android/server/inputmethod/InputMethodSettingsRepository.java @@ -19,15 +19,13 @@ package com.android.server.inputmethod; import android.annotation.AnyThread; import android.annotation.NonNull; import android.annotation.UserIdInt; -import android.util.SparseArray; - -import com.android.internal.annotations.GuardedBy; final class InputMethodSettingsRepository { - // TODO(b/352594784): Should we user other lock primitives? - @GuardedBy("sPerUserMap") + private static final Object sMutationLock = new Object(); + @NonNull - private static final SparseArray<InputMethodSettings> sPerUserMap = new SparseArray<>(); + private static volatile ImmutableSparseArray<InputMethodSettings> sPerUserMap = + ImmutableSparseArray.empty(); /** * Not intended to be instantiated. @@ -38,10 +36,7 @@ final class InputMethodSettingsRepository { @NonNull @AnyThread static InputMethodSettings get(@UserIdInt int userId) { - final InputMethodSettings obj; - synchronized (sPerUserMap) { - obj = sPerUserMap.get(userId); - } + final InputMethodSettings obj = sPerUserMap.get(userId); if (obj != null) { return obj; } @@ -50,15 +45,15 @@ final class InputMethodSettingsRepository { @AnyThread static void put(@UserIdInt int userId, @NonNull InputMethodSettings obj) { - synchronized (sPerUserMap) { - sPerUserMap.put(userId, obj); + synchronized (sMutationLock) { + sPerUserMap = sPerUserMap.cloneWithPutOrSelf(userId, obj); } } @AnyThread static void remove(@UserIdInt int userId) { - synchronized (sPerUserMap) { - sPerUserMap.remove(userId); + synchronized (sMutationLock) { + sPerUserMap = sPerUserMap.cloneWithRemoveOrSelf(userId); } } } diff --git a/services/core/java/com/android/server/inputmethod/SecureSettingsWrapper.java b/services/core/java/com/android/server/inputmethod/SecureSettingsWrapper.java index e7cff20ea2cb..476888ebf26d 100644 --- a/services/core/java/com/android/server/inputmethod/SecureSettingsWrapper.java +++ b/services/core/java/com/android/server/inputmethod/SecureSettingsWrapper.java @@ -20,11 +20,13 @@ import android.annotation.AnyThread; import android.annotation.NonNull; import android.annotation.Nullable; import android.annotation.UserIdInt; +import android.app.ActivityManagerInternal; import android.content.ContentResolver; +import android.content.Context; +import android.content.pm.UserInfo; import android.provider.Settings; import android.util.ArrayMap; import android.util.ArraySet; -import android.util.SparseArray; import com.android.internal.annotations.GuardedBy; import com.android.server.LocalServices; @@ -38,6 +40,13 @@ import com.android.server.pm.UserManagerInternal; * to the persistent value when the user storage is unlocked.</p> */ final class SecureSettingsWrapper { + + private static final Object sMutationLock = new Object(); + + @NonNull + private static volatile ImmutableSparseArray<ReaderWriter> sUserMap = + ImmutableSparseArray.empty(); + @Nullable private static volatile ContentResolver sContentResolver = null; @@ -61,8 +70,8 @@ final class SecureSettingsWrapper { */ @AnyThread static void endTestMode() { - synchronized (sUserMap) { - sUserMap.clear(); + synchronized (sMutationLock) { + sUserMap = ImmutableSparseArray.empty(); } sTestMode = false; } @@ -243,10 +252,6 @@ final class SecureSettingsWrapper { } } - @GuardedBy("sUserMap") - @NonNull - private static final SparseArray<ReaderWriter> sUserMap = new SparseArray<>(); - private static final ReaderWriter NOOP = new ReaderWriter() { @Override public void putString(String key, String str) { @@ -282,15 +287,15 @@ final class SecureSettingsWrapper { private static ReaderWriter putOrGet(@UserIdInt int userId, @NonNull ReaderWriter readerWriter) { final boolean isUnlockedUserImpl = readerWriter instanceof UnlockedUserImpl; - synchronized (sUserMap) { + synchronized (sMutationLock) { final ReaderWriter current = sUserMap.get(userId); if (current == null) { - sUserMap.put(userId, readerWriter); + sUserMap = sUserMap.cloneWithPutOrSelf(userId, readerWriter); return readerWriter; } // Upgrading from CopyOnWriteImpl to DirectImpl is allowed. if (current instanceof LockedUserImpl && isUnlockedUserImpl) { - sUserMap.put(userId, readerWriter); + sUserMap = sUserMap.cloneWithPutOrSelf(userId, readerWriter); return readerWriter; } return current; @@ -300,11 +305,9 @@ final class SecureSettingsWrapper { @NonNull @AnyThread private static ReaderWriter get(@UserIdInt int userId) { - synchronized (sUserMap) { - final ReaderWriter readerWriter = sUserMap.get(userId); - if (readerWriter != null) { - return readerWriter; - } + final ReaderWriter readerWriter = sUserMap.get(userId); + if (readerWriter != null) { + return readerWriter; } if (sTestMode) { return putOrGet(userId, new FakeReaderWriterImpl()); @@ -318,13 +321,30 @@ final class SecureSettingsWrapper { } /** - * Called when the system is starting. + * Called when {@link InputMethodManagerService} is starting. * - * @param contentResolver the {@link ContentResolver} to be used + * @param context the {@link Context} to be used. */ @AnyThread - static void setContentResolver(@NonNull ContentResolver contentResolver) { - sContentResolver = contentResolver; + static void onStart(@NonNull Context context) { + sContentResolver = context.getContentResolver(); + + final int userId = LocalServices.getService(ActivityManagerInternal.class) + .getCurrentUserId(); + final UserManagerInternal userManagerInternal = + LocalServices.getService(UserManagerInternal.class); + putOrGet(userId, createImpl(userManagerInternal, userId)); + + userManagerInternal.addUserLifecycleListener( + new UserManagerInternal.UserLifecycleListener() { + @Override + public void onUserRemoved(UserInfo user) { + synchronized (sMutationLock) { + sUserMap = sUserMap.cloneWithRemoveOrSelf(user.id); + } + } + } + ); } /** @@ -357,14 +377,19 @@ final class SecureSettingsWrapper { } /** - * Called when a user is being removed. + * Called when a user is stopped, which changes the user storage to the locked state again. * - * @param userId the ID of the user whose storage is being removed. + * @param userId the ID of the user whose storage is being locked again. */ @AnyThread - static void onUserRemoved(@UserIdInt int userId) { - synchronized (sUserMap) { - sUserMap.remove(userId); + static void onUserStopped(@UserIdInt int userId) { + final LockedUserImpl lockedUserImpl = new LockedUserImpl(userId, sContentResolver); + synchronized (sMutationLock) { + final ReaderWriter current = sUserMap.get(userId); + if (current == null || current instanceof LockedUserImpl) { + return; + } + sUserMap = sUserMap.cloneWithPutOrSelf(userId, lockedUserImpl); } } diff --git a/services/core/java/com/android/server/inputmethod/UserDataRepository.java b/services/core/java/com/android/server/inputmethod/UserDataRepository.java index 6f831cc29026..e3524b1f05e6 100644 --- a/services/core/java/com/android/server/inputmethod/UserDataRepository.java +++ b/services/core/java/com/android/server/inputmethod/UserDataRepository.java @@ -19,51 +19,39 @@ package com.android.server.inputmethod; import android.annotation.AnyThread; import android.annotation.NonNull; import android.annotation.UserIdInt; -import android.util.SparseArray; -import com.android.internal.annotations.GuardedBy; - -import java.util.concurrent.locks.ReentrantReadWriteLock; import java.util.function.Consumer; import java.util.function.IntFunction; final class UserDataRepository { - private final ReentrantReadWriteLock mUserDataLock = new ReentrantReadWriteLock(); + private final Object mMutationLock = new Object(); - @GuardedBy("mUserDataLock") - private final SparseArray<UserData> mUserData = new SparseArray<>(); + @NonNull + private volatile ImmutableSparseArray<UserData> mUserData = ImmutableSparseArray.empty(); private final IntFunction<InputMethodBindingController> mBindingControllerFactory; @AnyThread @NonNull UserData getOrCreate(@UserIdInt int userId) { - mUserDataLock.writeLock().lock(); - try { - UserData userData = mUserData.get(userId); - if (userData == null) { - userData = new UserData(userId, mBindingControllerFactory.apply(userId)); - mUserData.put(userId, userData); - } + // Do optimistic read first for optimization. + final var userData = mUserData.get(userId); + if (userData != null) { return userData; - } finally { - mUserDataLock.writeLock().unlock(); + } + // Note that the below line can be called concurrently. Here we assume that + // instantiating UserData for the same user multiple times would have no side effect. + final var newUserData = new UserData(userId, mBindingControllerFactory.apply(userId)); + synchronized (mMutationLock) { + mUserData = mUserData.cloneWithPutOrSelf(userId, newUserData); + return newUserData; } } @AnyThread void forAllUserData(Consumer<UserData> consumer) { - final SparseArray<UserData> copiedArray; - mUserDataLock.readLock().lock(); - try { - copiedArray = mUserData.clone(); - } finally { - mUserDataLock.readLock().unlock(); - } - for (int i = 0; i < copiedArray.size(); i++) { - consumer.accept(copiedArray.valueAt(i)); - } + mUserData.forEach(consumer); } UserDataRepository( @@ -73,11 +61,8 @@ final class UserDataRepository { @AnyThread void remove(@UserIdInt int userId) { - mUserDataLock.writeLock().lock(); - try { - mUserData.remove(userId); - } finally { - mUserDataLock.writeLock().unlock(); + synchronized (mMutationLock) { + mUserData = mUserData.cloneWithRemoveOrSelf(userId); } } } diff --git a/services/core/java/com/android/server/inputmethod/ZeroJankProxy.java b/services/core/java/com/android/server/inputmethod/ZeroJankProxy.java index fdb2e6faf91b..c940a9cd7b81 100644 --- a/services/core/java/com/android/server/inputmethod/ZeroJankProxy.java +++ b/services/core/java/com/android/server/inputmethod/ZeroJankProxy.java @@ -252,7 +252,9 @@ final class ZeroJankProxy implements IInputMethodManagerImpl.Callback { offload(() -> mInner.showInputMethodPickerFromClient(client, auxiliarySubtypeMode)); } - @IInputMethodManagerImpl.PermissionVerified(Manifest.permission.WRITE_SECURE_SETTINGS) + @IInputMethodManagerImpl.PermissionVerified(allOf = { + Manifest.permission.INTERACT_ACROSS_USERS_FULL, + Manifest.permission.WRITE_SECURE_SETTINGS}) @Override public void showInputMethodPickerFromSystem(int auxiliarySubtypeMode, int displayId) { mInner.showInputMethodPickerFromSystem(auxiliarySubtypeMode, displayId); @@ -264,7 +266,9 @@ final class ZeroJankProxy implements IInputMethodManagerImpl.Callback { return mInner.isInputMethodPickerShownForTest(); } - @IInputMethodManagerImpl.PermissionVerified(Manifest.permission.WRITE_SECURE_SETTINGS) + @IInputMethodManagerImpl.PermissionVerified(allOf = { + Manifest.permission.INTERACT_ACROSS_USERS_FULL, + Manifest.permission.WRITE_SECURE_SETTINGS}) @Override public void onImeSwitchButtonClickFromSystem(int displayId) { mInner.onImeSwitchButtonClickFromSystem(displayId); @@ -298,10 +302,12 @@ final class ZeroJankProxy implements IInputMethodManagerImpl.Callback { mInner.reportPerceptibleAsync(windowToken, perceptible); } - @IInputMethodManagerImpl.PermissionVerified(Manifest.permission.INTERNAL_SYSTEM_WINDOW) + @IInputMethodManagerImpl.PermissionVerified(allOf = { + Manifest.permission.INTERACT_ACROSS_USERS_FULL, + Manifest.permission.INTERNAL_SYSTEM_WINDOW}) @Override - public void removeImeSurface() { - mInner.removeImeSurface(); + public void removeImeSurface(int displayId) { + mInner.removeImeSurface(displayId); } @Override diff --git a/services/core/java/com/android/server/net/Android.bp b/services/core/java/com/android/server/net/Android.bp index 3ac2d232dfc8..68dc7816c5a4 100644 --- a/services/core/java/com/android/server/net/Android.bp +++ b/services/core/java/com/android/server/net/Android.bp @@ -9,3 +9,10 @@ java_aconfig_library { name: "net_flags_lib", aconfig_declarations: "net_flags", } + +java_aconfig_library { + name: "net_flags_host_lib", + aconfig_declarations: "net_flags", + host_supported: true, + mode: "test", +} diff --git a/services/core/java/com/android/server/notification/ManagedServices.java b/services/core/java/com/android/server/notification/ManagedServices.java index 1a8e44b526dd..1fdb57c0b61a 100644 --- a/services/core/java/com/android/server/notification/ManagedServices.java +++ b/services/core/java/com/android/server/notification/ManagedServices.java @@ -950,7 +950,7 @@ abstract public class ManagedServices { || isPackageOrComponentAllowed(component.getPackageName(), userId))) { return false; } - return componentHasBindPermission(component, userId); + return isValidService(component, userId); } private boolean componentHasBindPermission(ComponentName component, int userId) { @@ -1302,11 +1302,12 @@ abstract public class ManagedServices { if (TextUtils.equals(getPackageName(approvedPackageOrComponent), packageName)) { final ComponentName component = ComponentName.unflattenFromString( approvedPackageOrComponent); - if (component != null && !componentHasBindPermission(component, userId)) { + if (component != null && !isValidService(component, userId)) { approved.removeAt(j); if (DEBUG) { Slog.v(TAG, "Removing " + approvedPackageOrComponent - + " from approved list; no bind permission found " + + " from approved list; no bind permission or " + + "service interface filter found " + mConfig.bindPermission); } } @@ -1325,6 +1326,11 @@ abstract public class ManagedServices { } } + protected boolean isValidService(ComponentName component, int userId) { + return componentHasBindPermission(component, userId) && queryPackageForServices( + component.getPackageName(), userId).contains(component); + } + protected boolean isValidEntry(String packageOrComponent, int userId) { return hasMatchingServices(packageOrComponent, userId); } diff --git a/services/core/java/com/android/server/notification/NotificationManagerService.java b/services/core/java/com/android/server/notification/NotificationManagerService.java index 016abff88299..4179eddc7bc4 100644 --- a/services/core/java/com/android/server/notification/NotificationManagerService.java +++ b/services/core/java/com/android/server/notification/NotificationManagerService.java @@ -1315,10 +1315,24 @@ public class NotificationManagerService extends SystemService { nv.rank, nv.count); StatusBarNotification sbn = r.getSbn(); - cancelNotification(callingUid, callingPid, sbn.getPackageName(), sbn.getTag(), - sbn.getId(), FLAG_AUTO_CANCEL, - FLAG_FOREGROUND_SERVICE | FLAG_USER_INITIATED_JOB | FLAG_BUBBLE, - false, r.getUserId(), REASON_CLICK, nv.rank, nv.count, null); + // Notifications should be cancelled on click if they have been lifetime extended, + // regardless of presence or absence of FLAG_AUTO_CANCEL. + if (lifetimeExtensionRefactor() + && (sbn.getNotification().flags + & FLAG_LIFETIME_EXTENDED_BY_DIRECT_REPLY) != 0) { + cancelNotification(callingUid, callingPid, sbn.getPackageName(), sbn.getTag(), + sbn.getId(), FLAG_LIFETIME_EXTENDED_BY_DIRECT_REPLY, + FLAG_FOREGROUND_SERVICE | FLAG_USER_INITIATED_JOB + | FLAG_BUBBLE, + false, r.getUserId(), REASON_CLICK, nv.rank, nv.count, null); + + } else { + // Otherwise, only FLAG_AUTO_CANCEL notifications should be canceled on click. + cancelNotification(callingUid, callingPid, sbn.getPackageName(), sbn.getTag(), + sbn.getId(), FLAG_AUTO_CANCEL, + FLAG_FOREGROUND_SERVICE | FLAG_USER_INITIATED_JOB | FLAG_BUBBLE, + false, r.getUserId(), REASON_CLICK, nv.rank, nv.count, null); + } nv.recycle(); reportUserInteraction(r); mAssistants.notifyAssistantNotificationClicked(r); diff --git a/services/core/java/com/android/server/pm/BackgroundUserSoundNotifier.java b/services/core/java/com/android/server/pm/BackgroundUserSoundNotifier.java index 15e758cf6ffd..cf0c6c2cd992 100644 --- a/services/core/java/com/android/server/pm/BackgroundUserSoundNotifier.java +++ b/services/core/java/com/android/server/pm/BackgroundUserSoundNotifier.java @@ -236,6 +236,7 @@ public class BackgroundUserSoundNotifier { return new Notification.Builder(mSystemUserContext, BUSN_CHANNEL_ID) .setSmallIcon(icon) .setTicker(title) + .setCategory(Notification.CATEGORY_REMINDER) .setWhen(0) .setOngoing(true) .setColor(fgContext.getColor(R.color.system_notification_accent_color)) diff --git a/services/core/java/com/android/server/pm/InstallPackageHelper.java b/services/core/java/com/android/server/pm/InstallPackageHelper.java index 8d3f07edb687..a0d5ea875abf 100644 --- a/services/core/java/com/android/server/pm/InstallPackageHelper.java +++ b/services/core/java/com/android/server/pm/InstallPackageHelper.java @@ -501,9 +501,9 @@ final class InstallPackageHelper { mPm.setUpCustomResolverActivity(pkg, pkgSetting); } - // When upgrading a package, pkgSetting is copied from oldPkgSetting. Clear the app - // metadata file path for the new package. - if (oldPkgSetting != null) { + // When upgrading a package, clear the app metadata file path for the new package. + if (oldPkgSetting != null + && oldPkgSetting.getLastUpdateTime() < pkgSetting.getLastUpdateTime()) { pkgSetting.setAppMetadataFilePath(null); pkgSetting.setAppMetadataSource(APP_METADATA_SOURCE_UNKNOWN); } @@ -3264,6 +3264,7 @@ final class InstallPackageHelper { /** * Tries to restore the disabled system package after an update has been deleted. */ + @GuardedBy("mPm.mInstallLock") public void restoreDisabledSystemPackageLIF(DeletePackageAction action, @NonNull int[] allUserHandles, boolean writeSettings) throws SystemDeleteException { final PackageSetting deletedPs = action.mDeletingPs; @@ -3282,10 +3283,21 @@ final class InstallPackageHelper { } // Install the system package if (DEBUG_REMOVE) Slog.d(TAG, "Re-installing system package: " + disabledPs); - try (PackageManagerTracedLock installLock = mPm.mInstallLock.acquireLock()) { + try { final int[] origUsers = outInfo == null ? null : outInfo.mOrigUsers; - installPackageFromSystemLIF(disabledPs.getPathString(), allUserHandles, - origUsers, writeSettings); + try (PackageManagerTracedLock installLock = mPm.mInstallLock.acquireLock()) { + installPackageFromSystemLIF(disabledPs.getPathString(), allUserHandles, + origUsers, writeSettings); + } + if (origUsers != null) { + mPm.commitPackageStateMutation(null, mutator -> { + for (int userId : origUsers) { + mutator.forPackage(disabledPs.getPackageName()) + .userState(userId) + .setOverlayPaths(deletedPs.getOverlayPaths(userId)); + } + }); + } } catch (PackageManagerException e) { Slog.w(TAG, "Failed to restore system package:" + deletedPs.getPackageName() + ": " + e.getMessage()); @@ -3813,13 +3825,13 @@ final class InstallPackageHelper { // This also has the (beneficial) side effect where if a package disappears from an // APEX, leaving only a /data copy, it will lose its apexModuleName. // - // This must be done before scanSystemPackageLI as that will throw in the case of a + // This must be done before scanPackageForInitLI as that will throw in the case of a // system -> data package. disabledPkgSetting.setApexModuleName(activeApexInfo.apexModuleName); } } - final Pair<ScanResult, Boolean> scanResultPair = scanSystemPackageLI( + final Pair<ScanResult, Boolean> scanResultPair = scanPackageForInitLI( parsedPackage, parseFlags, scanFlags, user); final ScanResult scanResult = scanResultPair.first; boolean shouldHideSystemApp = scanResultPair.second; @@ -4054,7 +4066,7 @@ final class InstallPackageHelper { } } - private Pair<ScanResult, Boolean> scanSystemPackageLI(ParsedPackage parsedPackage, + private Pair<ScanResult, Boolean> scanPackageForInitLI(ParsedPackage parsedPackage, @ParsingPackageUtils.ParseFlags int parseFlags, @PackageManagerService.ScanFlags int scanFlags, @Nullable UserHandle user) throws PackageManagerException { @@ -4167,7 +4179,7 @@ final class InstallPackageHelper { ParsingPackageUtils.getSigningDetails(input, parsedPackage, false /*skipVerify*/); if (result.isError()) { - throw new PrepareFailure("Failed collect during scanSystemPackageLI", + throw new PrepareFailure("Failed collect during scanPackageForInitLI", result.getException()); } disabledPkgSetting.setSigningDetails(result.getResult()); diff --git a/services/core/java/com/android/server/pm/PackageManagerServiceUtils.java b/services/core/java/com/android/server/pm/PackageManagerServiceUtils.java index a1dffc6c25be..975758241e77 100644 --- a/services/core/java/com/android/server/pm/PackageManagerServiceUtils.java +++ b/services/core/java/com/android/server/pm/PackageManagerServiceUtils.java @@ -1452,6 +1452,13 @@ public class PackageManagerServiceUtils { } if (!ArrayUtils.isEmpty(after.splitNames)) { + if (beforeSplitNames.length != beforeSplitRevisionCodes.length) { + throw new PackageManagerException(INSTALL_FAILED_VERSION_DOWNGRADE, + "Current split names and the split revision codes are not 1:1 mapping." + + "This indicates that the package info data has been" + + " corrupted."); + } + for (int i = 0; i < after.splitNames.length; i++) { final String splitName = after.splitNames[i]; final int j = ArrayUtils.indexOf(beforeSplitNames, splitName); diff --git a/services/core/java/com/android/server/pm/Settings.java b/services/core/java/com/android/server/pm/Settings.java index 9177e2b75891..b7dfd8d0f8cd 100644 --- a/services/core/java/com/android/server/pm/Settings.java +++ b/services/core/java/com/android/server/pm/Settings.java @@ -4489,10 +4489,24 @@ public final class Settings implements Watchable, Snappable, ResilientAtomicFile String splitName = parser.getAttributeValue(null, ATTR_NAME); int splitRevision = parser.getAttributeInt(null, ATTR_VERSION, -1); if (splitName != null && splitRevision >= 0) { + final int beforeSplitNamesLength = outPs.getSplitNames().length; + // If the split name already exists in the outPs#getSplitNames, don't add it + // into the array and update its revision code below outPs.setSplitNames(ArrayUtils.appendElement(String.class, outPs.getSplitNames(), splitName)); - outPs.setSplitRevisionCodes(ArrayUtils.appendInt( - outPs.getSplitRevisionCodes(), splitRevision)); + + // If the same split name has already been added before, update the latest + // revision code + final int afterSplitNamesLength = outPs.getSplitNames().length; + if (beforeSplitNamesLength == afterSplitNamesLength) { + final int index = ArrayUtils.indexOf(outPs.getSplitNames(), splitName); + final int[] splitRevisionCodes = outPs.getSplitRevisionCodes(); + splitRevisionCodes[index] = splitRevision; + outPs.setSplitRevisionCodes(splitRevisionCodes); + } else { + outPs.setSplitRevisionCodes(ArrayUtils.appendInt( + outPs.getSplitRevisionCodes(), splitRevision, /* allowDuplicates= */ true)); + } } XmlUtils.skipCurrentTag(parser); diff --git a/services/core/java/com/android/server/policy/PhoneWindowManager.java b/services/core/java/com/android/server/policy/PhoneWindowManager.java index 7534bfe7b8ee..d0706d22a773 100644 --- a/services/core/java/com/android/server/policy/PhoneWindowManager.java +++ b/services/core/java/com/android/server/policy/PhoneWindowManager.java @@ -1158,8 +1158,7 @@ public class PhoneWindowManager implements WindowManagerPolicy { break; case SHORT_PRESS_POWER_CLOSE_IME_OR_GO_HOME: { if (mDismissImeOnBackKeyPressed) { - // TODO(b/308479256): Check if hiding "all" IMEs is OK or not. - InputMethodManagerInternal.get().hideAllInputMethods( + InputMethodManagerInternal.get().hideInputMethod( SoftInputShowHideReason.HIDE_POWER_BUTTON_GO_HOME, displayId); } else { shortPressPowerGoHome(); diff --git a/services/core/java/com/android/server/power/Notifier.java b/services/core/java/com/android/server/power/Notifier.java index aa5f5a24f179..b28da55b5196 100644 --- a/services/core/java/com/android/server/power/Notifier.java +++ b/services/core/java/com/android/server/power/Notifier.java @@ -375,9 +375,9 @@ public class Notifier { final boolean unimportantForLogging = newOwnerUid == Process.SYSTEM_UID && (newFlags & PowerManager.UNIMPORTANT_FOR_LOGGING) != 0; try { - mBatteryStats.noteChangeWakelockFromSource(workSource, ownerPid, tag, historyTag, - monitorType, newWorkSource, newOwnerPid, newTag, newHistoryTag, - newMonitorType, unimportantForLogging); + notifyWakelockChanging(workSource, ownerPid, tag, + historyTag, monitorType, newWorkSource, newOwnerPid, newTag, + newHistoryTag, newMonitorType, unimportantForLogging); } catch (RemoteException ex) { // Ignore } @@ -1127,6 +1127,29 @@ public class Notifier { mWakeLockLog.onWakeLockReleased(tag, ownerUid, currentTime); } + @SuppressLint("AndroidFrameworkRequiresPermission") + private void notifyWakelockChanging(WorkSource workSource, int ownerPid, String tag, + String historyTag, int monitorType, WorkSource newWorkSource, int newOwnerPid, + String newTag, String newHistoryTag, int newMonitorType, boolean unimportantForLogging) + throws RemoteException { + if (!mFlags.improveWakelockLatency()) { + mBatteryStats.noteChangeWakelockFromSource(workSource, ownerPid, tag, + historyTag, monitorType, newWorkSource, newOwnerPid, newTag, + newHistoryTag, newMonitorType, unimportantForLogging); + } else { + mHandler.post(() -> { + try { + mBatteryStats.noteChangeWakelockFromSource(workSource, ownerPid, tag, + historyTag, monitorType, newWorkSource, newOwnerPid, newTag, + newHistoryTag, newMonitorType, unimportantForLogging); + } catch (RemoteException e) { + Slog.e(TAG, "Failed to notify the wakelock changing from source via " + + "Notifier." + e.getLocalizedMessage()); + } + }); + } + } + private final class NotifierHandler extends Handler { public NotifierHandler(Looper looper) { diff --git a/services/core/java/com/android/server/power/PowerManagerService.java b/services/core/java/com/android/server/power/PowerManagerService.java index 10faf1455995..ecb0c30b13e4 100644 --- a/services/core/java/com/android/server/power/PowerManagerService.java +++ b/services/core/java/com/android/server/power/PowerManagerService.java @@ -34,6 +34,7 @@ import static android.os.PowerManagerInternal.wakefulnessToString; import static com.android.internal.util.LatencyTracker.ACTION_TURN_ON_SCREEN; import static com.android.server.deviceidle.Flags.disableWakelocksInLightIdle; import static com.android.server.display.DisplayDeviceConfig.INVALID_BRIGHTNESS_IN_CONFIG; +import static com.android.server.display.brightness.BrightnessUtils.isValidBrightnessValue; import android.annotation.IntDef; import android.annotation.NonNull; @@ -650,11 +651,16 @@ public final class PowerManagerService extends SystemService private int mDozeScreenStateOverrideReasonFromDreamManager = Display.STATE_REASON_UNKNOWN; - // The screen brightness to use while dozing. + // The screen brightness between 1 and 255 to use while dozing. private int mDozeScreenBrightnessOverrideFromDreamManager = PowerManager.BRIGHTNESS_DEFAULT; + /** + * The screen brightness between {@link PowerManager#BRIGHTNESS_MIN} and + * {@link PowerManager.BRIGHTNESS_MAX} to use while dozing. + */ private float mDozeScreenBrightnessOverrideFromDreamManagerFloat = PowerManager.BRIGHTNESS_INVALID_FLOAT; + // Keep display state when dozing. private boolean mDrawWakeLockOverrideFromSidekick; @@ -4455,15 +4461,21 @@ public final class PowerManagerService extends SystemService } private void setDozeOverrideFromDreamManagerInternal( - int screenState, @Display.StateReason int reason, int screenBrightness) { + int screenState, @Display.StateReason int reason, float screenBrightnessFloat, + int screenBrightnessInt) { synchronized (mLock) { if (mDozeScreenStateOverrideFromDreamManager != screenState - || mDozeScreenBrightnessOverrideFromDreamManager != screenBrightness) { + || mDozeScreenBrightnessOverrideFromDreamManager != screenBrightnessInt + || !BrightnessSynchronizer.floatEquals( + mDozeScreenBrightnessOverrideFromDreamManagerFloat, + screenBrightnessFloat)) { mDozeScreenStateOverrideFromDreamManager = screenState; mDozeScreenStateOverrideReasonFromDreamManager = reason; - mDozeScreenBrightnessOverrideFromDreamManager = screenBrightness; + mDozeScreenBrightnessOverrideFromDreamManager = screenBrightnessInt; mDozeScreenBrightnessOverrideFromDreamManagerFloat = - BrightnessSynchronizer.brightnessIntToFloat(mDozeScreenBrightnessOverrideFromDreamManager); + isValidBrightnessValue(screenBrightnessFloat) + ? screenBrightnessFloat + : BrightnessSynchronizer.brightnessIntToFloat(screenBrightnessInt); mDirty |= DIRTY_SETTINGS; updatePowerStateLocked(); } @@ -7095,7 +7107,7 @@ public final class PowerManagerService extends SystemService @Override public void setDozeOverrideFromDreamManager( - int screenState, int reason, int screenBrightness) { + int screenState, int reason, float screenBrightnessFloat, int screenBrightnessInt) { switch (screenState) { case Display.STATE_UNKNOWN: case Display.STATE_OFF: @@ -7108,11 +7120,17 @@ public final class PowerManagerService extends SystemService screenState = Display.STATE_UNKNOWN; break; } - if (screenBrightness < PowerManager.BRIGHTNESS_DEFAULT - || screenBrightness > PowerManager.BRIGHTNESS_ON) { - screenBrightness = PowerManager.BRIGHTNESS_DEFAULT; + if (screenBrightnessInt < PowerManager.BRIGHTNESS_DEFAULT + || screenBrightnessInt > PowerManager.BRIGHTNESS_ON) { + screenBrightnessInt = PowerManager.BRIGHTNESS_DEFAULT; + } + if (screenBrightnessFloat != PowerManager.BRIGHTNESS_OFF_FLOAT + && (screenBrightnessFloat < PowerManager.BRIGHTNESS_MIN + || screenBrightnessFloat > PowerManager.BRIGHTNESS_MAX)) { + screenBrightnessFloat = PowerManager.BRIGHTNESS_INVALID_FLOAT; } - setDozeOverrideFromDreamManagerInternal(screenState, reason, screenBrightness); + setDozeOverrideFromDreamManagerInternal(screenState, reason, screenBrightnessFloat, + screenBrightnessInt); } @Override diff --git a/services/core/java/com/android/server/power/hint/TEST_MAPPING b/services/core/java/com/android/server/power/hint/TEST_MAPPING index 34c25c6eb360..545070050977 100644 --- a/services/core/java/com/android/server/power/hint/TEST_MAPPING +++ b/services/core/java/com/android/server/power/hint/TEST_MAPPING @@ -1,27 +1,18 @@ { "presubmit": [ { - "name": "FrameworksServicesTests", + "name": "PerformanceHintTests", "options": [ - { - "include-filter": "com.android.server.power.hint" - }, - { - "exclude-annotation": "androidx.test.filters.FlakyTest" - } + {"exclude-annotation": "androidx.test.filters.FlakyTest"}, + {"exclude-annotation": "org.junit.Ignore"} ] - } - ], - "postsubmit": [ + }, { "name": "CtsStatsdAtomHostTestCases", "options": [ + {"include-filter": "android.cts.statsdatom.performancehintmanager"}, {"exclude-annotation": "androidx.test.filters.FlakyTest"}, - {"exclude-annotation": "org.junit.Ignore"}, - {"include-filter": "android.cts.statsdatom.performancehintmanager"} - ], - "file_patterns": [ - "(/|^)HintManagerService.java" + {"exclude-annotation": "org.junit.Ignore"} ] } ] diff --git a/services/core/java/com/android/server/power/stats/BatteryStatsImpl.java b/services/core/java/com/android/server/power/stats/BatteryStatsImpl.java index c4b37c6939b7..143b3ffa93af 100644 --- a/services/core/java/com/android/server/power/stats/BatteryStatsImpl.java +++ b/services/core/java/com/android/server/power/stats/BatteryStatsImpl.java @@ -5431,8 +5431,6 @@ public class BatteryStatsImpl extends BatteryStats { } } - int mSensorNesting; - @GuardedBy("this") public void noteStartSensorLocked(int uid, int sensor) { noteStartSensorLocked(uid, sensor, mClock.elapsedRealtime(), mClock.uptimeMillis()); @@ -5441,11 +5439,8 @@ public class BatteryStatsImpl extends BatteryStats { @GuardedBy("this") public void noteStartSensorLocked(int uid, int sensor, long elapsedRealtimeMs, long uptimeMs) { uid = mapUid(uid); - if (mSensorNesting == 0) { - mHistory.recordStateStartEvent(elapsedRealtimeMs, uptimeMs, - HistoryItem.STATE_SENSOR_ON_FLAG); - } - mSensorNesting++; + mHistory.recordStateStartEvent(elapsedRealtimeMs, uptimeMs, + HistoryItem.STATE_SENSOR_ON_FLAG, uid, "sensor:0x" + Integer.toHexString(sensor)); getUidStatsLocked(uid, elapsedRealtimeMs, uptimeMs) .noteStartSensor(sensor, elapsedRealtimeMs); } @@ -5458,11 +5453,8 @@ public class BatteryStatsImpl extends BatteryStats { @GuardedBy("this") public void noteStopSensorLocked(int uid, int sensor, long elapsedRealtimeMs, long uptimeMs) { uid = mapUid(uid); - mSensorNesting--; - if (mSensorNesting == 0) { - mHistory.recordStateStopEvent(elapsedRealtimeMs, uptimeMs, - HistoryItem.STATE_SENSOR_ON_FLAG); - } + mHistory.recordStateStopEvent(elapsedRealtimeMs, uptimeMs, + HistoryItem.STATE_SENSOR_ON_FLAG, uid, "sensor:0x" + Integer.toHexString(sensor)); getUidStatsLocked(uid, elapsedRealtimeMs, uptimeMs) .noteStopSensor(sensor, elapsedRealtimeMs); } diff --git a/services/core/java/com/android/server/power/stats/BatteryUsageStatsProvider.java b/services/core/java/com/android/server/power/stats/BatteryUsageStatsProvider.java index a5e4cf5a0e33..b308f3840383 100644 --- a/services/core/java/com/android/server/power/stats/BatteryUsageStatsProvider.java +++ b/services/core/java/com/android/server/power/stats/BatteryUsageStatsProvider.java @@ -93,8 +93,10 @@ public class BatteryUsageStatsProvider { if (!mPowerStatsExporterEnabled.get(BatteryConsumer.POWER_COMPONENT_BLUETOOTH)) { mPowerCalculators.add(new BluetoothPowerCalculator(mPowerProfile)); } - mPowerCalculators.add(new SensorPowerCalculator( - mContext.getSystemService(SensorManager.class))); + if (!mPowerStatsExporterEnabled.get(BatteryConsumer.POWER_COMPONENT_SENSORS)) { + mPowerCalculators.add(new SensorPowerCalculator( + mContext.getSystemService(SensorManager.class))); + } if (!mPowerStatsExporterEnabled.get(BatteryConsumer.POWER_COMPONENT_GNSS)) { mPowerCalculators.add(new GnssPowerCalculator(mPowerProfile)); } diff --git a/services/core/java/com/android/server/power/stats/PowerStatsExporter.java b/services/core/java/com/android/server/power/stats/PowerStatsExporter.java index 39954b8e8dba..5f41090da0a4 100644 --- a/services/core/java/com/android/server/power/stats/PowerStatsExporter.java +++ b/services/core/java/com/android/server/power/stats/PowerStatsExporter.java @@ -59,58 +59,61 @@ public class PowerStatsExporter { */ public void exportAggregatedPowerStats(BatteryUsageStats.Builder batteryUsageStatsBuilder, long monotonicStartTime, long monotonicEndTime) { - boolean hasStoredSpans = false; - long maxEndTime = monotonicStartTime; - List<PowerStatsSpan.Metadata> spans = mPowerStatsStore.getTableOfContents(); - for (int i = spans.size() - 1; i >= 0; i--) { - PowerStatsSpan.Metadata metadata = spans.get(i); - if (!metadata.getSections().contains(AggregatedPowerStatsSection.TYPE)) { - continue; - } + synchronized (this) { + boolean hasStoredSpans = false; + long maxEndTime = monotonicStartTime; + List<PowerStatsSpan.Metadata> spans = mPowerStatsStore.getTableOfContents(); + for (int i = spans.size() - 1; i >= 0; i--) { + PowerStatsSpan.Metadata metadata = spans.get(i); + if (!metadata.getSections().contains(AggregatedPowerStatsSection.TYPE)) { + continue; + } - List<PowerStatsSpan.TimeFrame> timeFrames = metadata.getTimeFrames(); - long spanMinTime = Long.MAX_VALUE; - long spanMaxTime = Long.MIN_VALUE; - for (int j = 0; j < timeFrames.size(); j++) { - PowerStatsSpan.TimeFrame timeFrame = timeFrames.get(j); - long startMonotonicTime = timeFrame.startMonotonicTime; - long endMonotonicTime = startMonotonicTime + timeFrame.duration; - if (startMonotonicTime < spanMinTime) { - spanMinTime = startMonotonicTime; + List<PowerStatsSpan.TimeFrame> timeFrames = metadata.getTimeFrames(); + long spanMinTime = Long.MAX_VALUE; + long spanMaxTime = Long.MIN_VALUE; + for (int j = 0; j < timeFrames.size(); j++) { + PowerStatsSpan.TimeFrame timeFrame = timeFrames.get(j); + long startMonotonicTime = timeFrame.startMonotonicTime; + long endMonotonicTime = startMonotonicTime + timeFrame.duration; + if (startMonotonicTime < spanMinTime) { + spanMinTime = startMonotonicTime; + } + if (endMonotonicTime > spanMaxTime) { + spanMaxTime = endMonotonicTime; + } } - if (endMonotonicTime > spanMaxTime) { - spanMaxTime = endMonotonicTime; + + if (!(spanMinTime >= monotonicStartTime && spanMaxTime < monotonicEndTime)) { + continue; } - } - if (!(spanMinTime >= monotonicStartTime && spanMaxTime < monotonicEndTime)) { - continue; - } + if (spanMaxTime > maxEndTime) { + maxEndTime = spanMaxTime; + } - if (spanMaxTime > maxEndTime) { - maxEndTime = spanMaxTime; + PowerStatsSpan span = mPowerStatsStore.loadPowerStatsSpan(metadata.getId(), + AggregatedPowerStatsSection.TYPE); + if (span == null) { + Slog.e(TAG, "Could not read PowerStatsStore section " + metadata); + continue; + } + List<PowerStatsSpan.Section> sections = span.getSections(); + for (int k = 0; k < sections.size(); k++) { + hasStoredSpans = true; + PowerStatsSpan.Section section = sections.get(k); + populateBatteryUsageStatsBuilder(batteryUsageStatsBuilder, + ((AggregatedPowerStatsSection) section).getAggregatedPowerStats()); + } } - PowerStatsSpan span = mPowerStatsStore.loadPowerStatsSpan(metadata.getId(), - AggregatedPowerStatsSection.TYPE); - if (span == null) { - Slog.e(TAG, "Could not read PowerStatsStore section " + metadata); - continue; - } - List<PowerStatsSpan.Section> sections = span.getSections(); - for (int k = 0; k < sections.size(); k++) { - hasStoredSpans = true; - PowerStatsSpan.Section section = sections.get(k); - populateBatteryUsageStatsBuilder(batteryUsageStatsBuilder, - ((AggregatedPowerStatsSection) section).getAggregatedPowerStats()); + if (!hasStoredSpans + || maxEndTime < monotonicEndTime - mBatterySessionTimeSpanSlackMillis) { + mPowerStatsAggregator.aggregatePowerStats(maxEndTime, monotonicEndTime, + stats -> populateBatteryUsageStatsBuilder(batteryUsageStatsBuilder, stats)); } + mPowerStatsAggregator.reset(); } - - if (!hasStoredSpans || maxEndTime < monotonicEndTime - mBatterySessionTimeSpanSlackMillis) { - mPowerStatsAggregator.aggregatePowerStats(maxEndTime, monotonicEndTime, - stats -> populateBatteryUsageStatsBuilder(batteryUsageStatsBuilder, stats)); - } - mPowerStatsAggregator.reset(); } private void populateBatteryUsageStatsBuilder( diff --git a/services/core/java/com/android/server/power/stats/PowerStatsProcessor.java b/services/core/java/com/android/server/power/stats/PowerStatsProcessor.java index 7d7b3c2fa3c5..c81c7ffe5371 100644 --- a/services/core/java/com/android/server/power/stats/PowerStatsProcessor.java +++ b/services/core/java/com/android/server/power/stats/PowerStatsProcessor.java @@ -257,8 +257,8 @@ public abstract class PowerStatsProcessor { for (int i = deviceStateEstimations.size() - 1; i >= 0; i--) { deviceStateEstimations.get(i).intermediates = null; } - for (int i = deviceStateEstimations.size() - 1; i >= 0; i--) { - deviceStateEstimations.get(i).intermediates = null; + for (int i = combinedDeviceStateEstimations.size() - 1; i >= 0; i--) { + combinedDeviceStateEstimations.get(i).intermediates = null; } for (int i = uidStateEstimates.size() - 1; i >= 0; i--) { UidStateEstimate uidStateEstimate = uidStateEstimates.get(i); diff --git a/services/core/java/com/android/server/power/stats/ScreenPowerStatsProcessor.java b/services/core/java/com/android/server/power/stats/ScreenPowerStatsProcessor.java index e203e4a4175b..908c75155f42 100644 --- a/services/core/java/com/android/server/power/stats/ScreenPowerStatsProcessor.java +++ b/services/core/java/com/android/server/power/stats/ScreenPowerStatsProcessor.java @@ -119,6 +119,7 @@ public class ScreenPowerStatsProcessor extends PowerStatsProcessor { if (!uids.isEmpty()) { computeUidPowerEstimates(stats, uids); } + mPlan.resetIntermediates(); } private void computeDevicePowerEstimates(PowerComponentAggregatedPowerStats stats) { diff --git a/services/core/java/com/android/server/power/stats/SensorPowerStatsLayout.java b/services/core/java/com/android/server/power/stats/SensorPowerStatsLayout.java new file mode 100644 index 000000000000..e66cd3970d2f --- /dev/null +++ b/services/core/java/com/android/server/power/stats/SensorPowerStatsLayout.java @@ -0,0 +1,81 @@ +/* + * Copyright (C) 2024 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.android.server.power.stats; + +import android.os.PersistableBundle; +import android.util.Slog; +import android.util.SparseIntArray; + +public class SensorPowerStatsLayout extends PowerStatsLayout { + private static final String TAG = "SensorPowerStatsLayout"; + private static final String EXTRA_DEVICE_SENSOR_HANDLES = "dsh"; + private static final String EXTRA_UID_SENSOR_POSITIONS = "usp"; + + private final SparseIntArray mSensorPositions = new SparseIntArray(); + + void addUidSensorSection(int handle, String label) { + mSensorPositions.put(handle, addUidSection(1, label, FLAG_OPTIONAL)); + } + + /** + * Returns the position in the uid stats array of the duration element corresponding + * to the specified sensor identified by its handle. + */ + public int getUidSensorDurationPosition(int handle) { + return mSensorPositions.get(handle, UNSUPPORTED); + } + + /** + * Adds the specified duration to the accumulated timer for the specified sensor. + */ + public void addUidSensorDuration(long[] stats, int handle, long durationMs) { + int position = mSensorPositions.get(handle, UNSUPPORTED); + if (position == UNSUPPORTED) { + Slog.e(TAG, "Unknown sensor: " + handle); + return; + } + stats[position] += durationMs; + } + + @Override + public void toExtras(PersistableBundle extras) { + super.toExtras(extras); + + int[] handlers = new int[mSensorPositions.size()]; + int[] uidDurationPositions = new int[mSensorPositions.size()]; + + for (int i = 0; i < mSensorPositions.size(); i++) { + handlers[i] = mSensorPositions.keyAt(i); + uidDurationPositions[i] = mSensorPositions.valueAt(i); + } + + extras.putIntArray(EXTRA_DEVICE_SENSOR_HANDLES, handlers); + extras.putIntArray(EXTRA_UID_SENSOR_POSITIONS, uidDurationPositions); + } + + @Override + public void fromExtras(PersistableBundle extras) { + super.fromExtras(extras); + + int[] handlers = extras.getIntArray(EXTRA_DEVICE_SENSOR_HANDLES); + int[] uidDurationPositions = extras.getIntArray(EXTRA_UID_SENSOR_POSITIONS); + + for (int i = 0; i < handlers.length; i++) { + mSensorPositions.put(handlers[i], uidDurationPositions[i]); + } + } +} diff --git a/services/core/java/com/android/server/power/stats/SensorPowerStatsProcessor.java b/services/core/java/com/android/server/power/stats/SensorPowerStatsProcessor.java new file mode 100644 index 000000000000..5bd32882c1b1 --- /dev/null +++ b/services/core/java/com/android/server/power/stats/SensorPowerStatsProcessor.java @@ -0,0 +1,312 @@ +/* + * Copyright (C) 2024 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.android.server.power.stats; + +import android.hardware.Sensor; +import android.hardware.SensorManager; +import android.os.BatteryConsumer; +import android.os.BatteryStats; +import android.os.PersistableBundle; +import android.util.Slog; +import android.util.SparseArray; + +import com.android.internal.os.PowerStats; + +import java.util.ArrayList; +import java.util.Arrays; +import java.util.Comparator; +import java.util.List; +import java.util.function.Supplier; + +public class SensorPowerStatsProcessor extends PowerStatsProcessor { + private static final String TAG = "SensorPowerStatsProcessor"; + private static final String ANDROID_SENSOR_TYPE_PREFIX = "android.sensor."; + + private static final double MILLIS_IN_HOUR = 1000.0 * 60 * 60; + private static final String SENSOR_EVENT_TAG_PREFIX = "sensor:0x"; + private final Supplier<SensorManager> mSensorManagerSupplier; + + private static final long INITIAL_TIMESTAMP = -1; + private SensorManager mSensorManager; + private SensorPowerStatsLayout mStatsLayout; + private PowerStats mPowerStats; + private boolean mIsInitialized; + private PowerStats.Descriptor mDescriptor; + private long mLastUpdateTimestamp; + private PowerEstimationPlan mPlan; + + private static class SensorState { + public int sensorHandle; + public boolean stateOn; + public int uid; + public long startTime = INITIAL_TIMESTAMP; + } + + private static class Intermediates { + public double power; + } + + private final SparseArray<SensorState> mSensorStates = new SparseArray<>(); + private long[] mTmpDeviceStatsArray; + private long[] mTmpUidStatsArray; + + public SensorPowerStatsProcessor(Supplier<SensorManager> sensorManagerSupplier) { + mSensorManagerSupplier = sensorManagerSupplier; + } + + private boolean ensureInitialized() { + if (mIsInitialized) { + return true; + } + + mSensorManager = mSensorManagerSupplier.get(); + if (mSensorManager == null) { + return false; + } + + mStatsLayout = new SensorPowerStatsLayout(); + List<Sensor> sensorList = new ArrayList<>(mSensorManager.getSensorList(Sensor.TYPE_ALL)); + sensorList.sort(Comparator.comparingInt(Sensor::getId)); + for (int i = 0; i < sensorList.size(); i++) { + Sensor sensor = sensorList.get(i); + String label = makeLabel(sensor, sensorList); + mStatsLayout.addUidSensorSection(sensor.getHandle(), label); + } + mStatsLayout.addUidSectionPowerEstimate(); + mStatsLayout.addDeviceSectionPowerEstimate(); + + PersistableBundle extras = new PersistableBundle(); + mStatsLayout.toExtras(extras); + mDescriptor = new PowerStats.Descriptor( + BatteryConsumer.POWER_COMPONENT_SENSORS, mStatsLayout.getDeviceStatsArrayLength(), + null, 0, mStatsLayout.getUidStatsArrayLength(), + extras); + + mPowerStats = new PowerStats(mDescriptor); + mTmpUidStatsArray = new long[mDescriptor.uidStatsArrayLength]; + mTmpDeviceStatsArray = new long[mDescriptor.statsArrayLength]; + + mIsInitialized = true; + return true; + } + + private String makeLabel(Sensor sensor, List<Sensor> sensorList) { + int type = sensor.getType(); + String label = sensor.getStringType(); + + boolean isSingleton = true; + for (int i = sensorList.size() - 1; i >= 0; i--) { + Sensor s = sensorList.get(i); + if (s == sensor) { + continue; + } + if (s.getType() == type) { + isSingleton = false; + break; + } + } + if (!isSingleton) { + StringBuilder sb = new StringBuilder(label).append('.'); + if (sensor.getId() > 0) { // 0 and -1 are reserved + sb.append(sensor.getId()); + } else { + sb.append(sensor.getName()); + } + label = sb.toString(); + } + if (label.startsWith(ANDROID_SENSOR_TYPE_PREFIX)) { + label = label.substring(ANDROID_SENSOR_TYPE_PREFIX.length()); + } + return label.replace(' ', '_'); + } + + @Override + void start(PowerComponentAggregatedPowerStats stats, long timestampMs) { + if (!ensureInitialized()) { + return; + } + + // Establish a baseline at the beginning of an accumulation pass + mLastUpdateTimestamp = timestampMs; + flushPowerStats(stats, timestampMs); + } + + @Override + void noteStateChange(PowerComponentAggregatedPowerStats stats, BatteryStats.HistoryItem item) { + if (!mIsInitialized) { + return; + } + + if (item.eventTag == null || item.eventTag.string == null + || !item.eventTag.string.startsWith(SENSOR_EVENT_TAG_PREFIX)) { + return; + } + + int sensorHandle; + try { + sensorHandle = Integer.parseInt(item.eventTag.string, SENSOR_EVENT_TAG_PREFIX.length(), + item.eventTag.string.length(), 16); + } catch (NumberFormatException e) { + Slog.wtf(TAG, "Bad format of event tag: " + item.eventTag.string); + return; + } + + SensorState sensor = mSensorStates.get(sensorHandle); + if (sensor == null) { + sensor = new SensorState(); + sensor.sensorHandle = sensorHandle; + mSensorStates.put(sensorHandle, sensor); + } + + int uid = item.eventTag.uid; + boolean sensorOn = (item.states & BatteryStats.HistoryItem.STATE_SENSOR_ON_FLAG) != 0; + if (sensorOn) { + if (!sensor.stateOn) { + sensor.stateOn = true; + sensor.uid = uid; + sensor.startTime = item.time; + } else if (sensor.uid != uid) { + recordUsageDuration(sensor, item.time); + sensor.uid = uid; + } + } else { + if (sensor.stateOn) { + recordUsageDuration(sensor, item.time); + sensor.stateOn = false; + } + } + } + + @Override + void finish(PowerComponentAggregatedPowerStats stats, long timestampMs) { + if (!mIsInitialized) { + return; + } + + for (int i = mSensorStates.size() - 1; i >= 0; i--) { + SensorState sensor = mSensorStates.valueAt(i); + if (sensor.stateOn) { + recordUsageDuration(sensor, timestampMs); + } + } + flushPowerStats(stats, timestampMs); + + if (mPlan == null) { + mPlan = new PowerEstimationPlan(stats.getConfig()); + } + + List<Integer> uids = new ArrayList<>(); + stats.collectUids(uids); + + computeUidPowerEstimates(stats, uids); + computeDevicePowerEstimates(stats); + + mPlan.resetIntermediates(); + } + + protected void recordUsageDuration(SensorState sensorState, long time) { + long durationMs = Math.max(0, time - sensorState.startTime); + if (durationMs > 0) { + long[] uidStats = mPowerStats.uidStats.get(sensorState.uid); + if (uidStats == null) { + uidStats = new long[mDescriptor.uidStatsArrayLength]; + mPowerStats.uidStats.put(sensorState.uid, uidStats); + } + mStatsLayout.addUidSensorDuration(uidStats, sensorState.sensorHandle, durationMs); + } + sensorState.startTime = time; + } + + private void flushPowerStats(PowerComponentAggregatedPowerStats stats, long timestamp) { + mPowerStats.durationMs = timestamp - mLastUpdateTimestamp; + stats.addPowerStats(mPowerStats, timestamp); + + Arrays.fill(mPowerStats.stats, 0); + mPowerStats.uidStats.clear(); + mLastUpdateTimestamp = timestamp; + } + + private void computeUidPowerEstimates(PowerComponentAggregatedPowerStats stats, + List<Integer> uids) { + List<Sensor> sensorList = mSensorManager.getSensorList(Sensor.TYPE_ALL); + int[] uidSensorDurationPositions = new int[sensorList.size()]; + double[] sensorPower = new double[sensorList.size()]; + for (int i = sensorList.size() - 1; i >= 0; i--) { + Sensor sensor = sensorList.get(i); + uidSensorDurationPositions[i] = + mStatsLayout.getUidSensorDurationPosition(sensor.getHandle()); + sensorPower[i] = sensor.getPower() / MILLIS_IN_HOUR; + } + + for (int i = mPlan.uidStateEstimates.size() - 1; i >= 0; i--) { + UidStateEstimate uidStateEstimate = mPlan.uidStateEstimates.get(i); + List<UidStateProportionalEstimate> proportionalEstimates = + uidStateEstimate.proportionalEstimates; + for (int j = proportionalEstimates.size() - 1; j >= 0; j--) { + UidStateProportionalEstimate proportionalEstimate = proportionalEstimates.get(j); + for (int k = uids.size() - 1; k >= 0; k--) { + int uid = uids.get(k); + if (!stats.getUidStats(mTmpUidStatsArray, uid, + proportionalEstimate.stateValues)) { + continue; + } + double power = 0; + for (int m = 0; m < uidSensorDurationPositions.length; m++) { + int position = uidSensorDurationPositions[m]; + if (position == PowerStatsLayout.UNSUPPORTED + || mTmpUidStatsArray[position] == 0) { + continue; + } + power += sensorPower[m] * mTmpUidStatsArray[position]; + } + if (power == 0) { + continue; + } + + mStatsLayout.setUidPowerEstimate(mTmpUidStatsArray, power); + stats.setUidStats(uid, proportionalEstimate.stateValues, mTmpUidStatsArray); + + Intermediates intermediates = (Intermediates) uidStateEstimate + .combinedDeviceStateEstimate.intermediates; + if (intermediates == null) { + intermediates = new Intermediates(); + uidStateEstimate.combinedDeviceStateEstimate.intermediates = intermediates; + } + intermediates.power += power; + } + } + } + } + + private void computeDevicePowerEstimates(PowerComponentAggregatedPowerStats stats) { + for (int i = mPlan.combinedDeviceStateEstimations.size() - 1; i >= 0; i--) { + CombinedDeviceStateEstimate estimation = + mPlan.combinedDeviceStateEstimations.get(i); + if (estimation.intermediates == null) { + continue; + } + + if (!stats.getDeviceStats(mTmpDeviceStatsArray, estimation.stateValues)) { + continue; + } + + mStatsLayout.setDevicePowerEstimate(mTmpDeviceStatsArray, + ((Intermediates) estimation.intermediates).power); + stats.setDeviceStats(estimation.stateValues, mTmpDeviceStatsArray); + } + } +} diff --git a/services/core/java/com/android/server/sensorprivacy/SensorPrivacyService.java b/services/core/java/com/android/server/sensorprivacy/SensorPrivacyService.java index 52ef87cf949f..06a2565da75a 100644 --- a/services/core/java/com/android/server/sensorprivacy/SensorPrivacyService.java +++ b/services/core/java/com/android/server/sensorprivacy/SensorPrivacyService.java @@ -130,6 +130,7 @@ import android.util.proto.ProtoOutputStream; import com.android.internal.R; import com.android.internal.annotations.GuardedBy; +import com.android.internal.annotations.KeepForWeakReference; import com.android.internal.camera.flags.Flags; import com.android.internal.messages.nano.SystemMessageProto.SystemMessage; import com.android.internal.os.BackgroundThread; @@ -1944,8 +1945,12 @@ public final class SensorPrivacyService extends SystemService { } private class CallStateHelper { - private OutgoingEmergencyStateCallback mEmergencyStateCallback; - private CallStateCallback mCallStateCallback; + // TelephonyCallback instances are only weakly referenced when registered, so we need + // to ensure these fields are kept during optimization to preserve lifecycle semantics. + @KeepForWeakReference + private final OutgoingEmergencyStateCallback mEmergencyStateCallback; + @KeepForWeakReference + private final CallStateCallback mCallStateCallback; private boolean mIsInEmergencyCall; private boolean mMicUnmutedForEmergencyCall; diff --git a/services/core/java/com/android/server/stats/pull/StatsPullAtomService.java b/services/core/java/com/android/server/stats/pull/StatsPullAtomService.java index bca81f52a1ac..c21f783003fa 100644 --- a/services/core/java/com/android/server/stats/pull/StatsPullAtomService.java +++ b/services/core/java/com/android/server/stats/pull/StatsPullAtomService.java @@ -64,6 +64,7 @@ import static com.android.internal.util.FrameworkStatsLog.TIME_ZONE_DETECTOR_STA import static com.android.internal.util.FrameworkStatsLog.TIME_ZONE_DETECTOR_STATE__DETECTION_MODE__UNKNOWN; import static com.android.server.am.MemoryStatUtil.readMemoryStatFromFilesystem; import static com.android.server.stats.Flags.addMobileBytesTransferByProcStatePuller; +import static com.android.server.stats.Flags.applyNetworkStatsPollRateLimit; import static com.android.server.stats.pull.IonMemoryUtil.readProcessSystemIonHeapSizesFromDebugfs; import static com.android.server.stats.pull.IonMemoryUtil.readSystemIonHeapSizeFromDebugfs; import static com.android.server.stats.pull.ProcfsMemoryUtil.getProcessCmdlines; @@ -298,6 +299,13 @@ public class StatsPullAtomService extends SystemService { */ private static final long NETSTATS_UID_DEFAULT_BUCKET_DURATION_MS = HOURS.toMillis(2); + /** + * Polling NetworkStats is a heavy operation and it should be done sparingly. Atom pulls may + * happen in bursts, but these should be infrequent. The poll rate limit ensures that data is + * sufficiently fresh (i.e. not stale) while reducing system load during atom pull bursts. + */ + private static final long NETSTATS_POLL_RATE_LIMIT_MS = 15000; + private static final int CPU_TIME_PER_THREAD_FREQ_MAX_NUM_FREQUENCIES = 8; private static final int OP_FLAGS_PULLED = OP_FLAG_SELF | OP_FLAG_TRUSTED_PROXIED; private static final String COMMON_PERMISSION_PREFIX = "android.permission."; @@ -415,6 +423,9 @@ public class StatsPullAtomService extends SystemService { @GuardedBy("mDataBytesTransferLock") private final ArrayList<NetworkStatsExt> mNetworkStatsBaselines = new ArrayList<>(); + @GuardedBy("mDataBytesTransferLock") + private long mLastNetworkStatsPollTime = -NETSTATS_POLL_RATE_LIMIT_MS; + // Listener for monitoring subscriptions changed event. private StatsSubscriptionsListener mStatsSubscriptionsListener; // List that stores SubInfo of subscriptions that ever appeared since boot. @@ -1063,24 +1074,26 @@ public class StatsPullAtomService extends SystemService { // Initialize NetworkStats baselines. synchronized (mDataBytesTransferLock) { mNetworkStatsBaselines.addAll( - collectNetworkStatsSnapshotForAtom(FrameworkStatsLog.WIFI_BYTES_TRANSFER)); + collectNetworkStatsSnapshotForAtomLocked( + FrameworkStatsLog.WIFI_BYTES_TRANSFER)); mNetworkStatsBaselines.addAll( - collectNetworkStatsSnapshotForAtom( + collectNetworkStatsSnapshotForAtomLocked( FrameworkStatsLog.WIFI_BYTES_TRANSFER_BY_FG_BG)); mNetworkStatsBaselines.addAll( - collectNetworkStatsSnapshotForAtom(FrameworkStatsLog.MOBILE_BYTES_TRANSFER)); - mNetworkStatsBaselines.addAll(collectNetworkStatsSnapshotForAtom( + collectNetworkStatsSnapshotForAtomLocked( + FrameworkStatsLog.MOBILE_BYTES_TRANSFER)); + mNetworkStatsBaselines.addAll(collectNetworkStatsSnapshotForAtomLocked( FrameworkStatsLog.MOBILE_BYTES_TRANSFER_BY_FG_BG)); - mNetworkStatsBaselines.addAll(collectNetworkStatsSnapshotForAtom( + mNetworkStatsBaselines.addAll(collectNetworkStatsSnapshotForAtomLocked( FrameworkStatsLog.BYTES_TRANSFER_BY_TAG_AND_METERED)); mNetworkStatsBaselines.addAll( - collectNetworkStatsSnapshotForAtom( + collectNetworkStatsSnapshotForAtomLocked( FrameworkStatsLog.DATA_USAGE_BYTES_TRANSFER)); mNetworkStatsBaselines.addAll( - collectNetworkStatsSnapshotForAtom( + collectNetworkStatsSnapshotForAtomLocked( FrameworkStatsLog.OEM_MANAGED_BYTES_TRANSFER)); if (canQueryTypeProxy) { - mNetworkStatsBaselines.addAll(collectNetworkStatsSnapshotForAtom( + mNetworkStatsBaselines.addAll(collectNetworkStatsSnapshotForAtomLocked( FrameworkStatsLog.PROXY_BYTES_TRANSFER_BY_FG_BG)); } } @@ -1243,12 +1256,14 @@ public class StatsPullAtomService extends SystemService { ); } + @GuardedBy("mDataBytesTransferLock") @NonNull - private List<NetworkStatsExt> collectNetworkStatsSnapshotForAtom(int atomTag) { + private List<NetworkStatsExt> collectNetworkStatsSnapshotForAtomLocked(int atomTag) { List<NetworkStatsExt> ret = new ArrayList<>(); switch (atomTag) { case FrameworkStatsLog.WIFI_BYTES_TRANSFER: { - final NetworkStats stats = getUidNetworkStatsSnapshotForTransport(TRANSPORT_WIFI); + final NetworkStats stats = getUidNetworkStatsSnapshotForTransportLocked( + TRANSPORT_WIFI); if (stats != null) { ret.add(new NetworkStatsExt(sliceNetworkStatsByUid(stats), new int[]{TRANSPORT_WIFI}, /*slicedByFgbg=*/false)); @@ -1256,7 +1271,8 @@ public class StatsPullAtomService extends SystemService { break; } case FrameworkStatsLog.WIFI_BYTES_TRANSFER_BY_FG_BG: { - final NetworkStats stats = getUidNetworkStatsSnapshotForTransport(TRANSPORT_WIFI); + final NetworkStats stats = getUidNetworkStatsSnapshotForTransportLocked( + TRANSPORT_WIFI); if (stats != null) { ret.add(new NetworkStatsExt(sliceNetworkStatsByUidAndFgbg(stats), new int[]{TRANSPORT_WIFI}, /*slicedByFgbg=*/true)); @@ -1265,7 +1281,7 @@ public class StatsPullAtomService extends SystemService { } case FrameworkStatsLog.MOBILE_BYTES_TRANSFER: { final NetworkStats stats = - getUidNetworkStatsSnapshotForTransport(TRANSPORT_CELLULAR); + getUidNetworkStatsSnapshotForTransportLocked(TRANSPORT_CELLULAR); if (stats != null) { ret.add(new NetworkStatsExt(sliceNetworkStatsByUid(stats), new int[]{TRANSPORT_CELLULAR}, /*slicedByFgbg=*/false)); @@ -1274,7 +1290,7 @@ public class StatsPullAtomService extends SystemService { } case FrameworkStatsLog.MOBILE_BYTES_TRANSFER_BY_FG_BG: { final NetworkStats stats = - getUidNetworkStatsSnapshotForTransport(TRANSPORT_CELLULAR); + getUidNetworkStatsSnapshotForTransportLocked(TRANSPORT_CELLULAR); if (stats != null) { ret.add(new NetworkStatsExt(sliceNetworkStatsByUidAndFgbg(stats), new int[]{TRANSPORT_CELLULAR}, /*slicedByFgbg=*/true)); @@ -1282,7 +1298,7 @@ public class StatsPullAtomService extends SystemService { break; } case FrameworkStatsLog.PROXY_BYTES_TRANSFER_BY_FG_BG: { - final NetworkStats stats = getUidNetworkStatsSnapshotForTemplate( + final NetworkStats stats = getUidNetworkStatsSnapshotForTemplateLocked( new NetworkTemplate.Builder(MATCH_PROXY).build(), /*includeTags=*/false); if (stats != null) { ret.add(new NetworkStatsExt(sliceNetworkStatsByUidTagAndMetered(stats), @@ -1294,9 +1310,9 @@ public class StatsPullAtomService extends SystemService { break; } case FrameworkStatsLog.BYTES_TRANSFER_BY_TAG_AND_METERED: { - final NetworkStats wifiStats = getUidNetworkStatsSnapshotForTemplate( + final NetworkStats wifiStats = getUidNetworkStatsSnapshotForTemplateLocked( new NetworkTemplate.Builder(MATCH_WIFI).build(), /*includeTags=*/true); - final NetworkStats cellularStats = getUidNetworkStatsSnapshotForTemplate( + final NetworkStats cellularStats = getUidNetworkStatsSnapshotForTemplateLocked( new NetworkTemplate.Builder(MATCH_MOBILE) .setMeteredness(METERED_YES).build(), /*includeTags=*/true); if (wifiStats != null && cellularStats != null) { @@ -1311,12 +1327,12 @@ public class StatsPullAtomService extends SystemService { } case FrameworkStatsLog.DATA_USAGE_BYTES_TRANSFER: { for (final SubInfo subInfo : mHistoricalSubs) { - ret.addAll(getDataUsageBytesTransferSnapshotForSub(subInfo)); + ret.addAll(getDataUsageBytesTransferSnapshotForSubLocked(subInfo)); } break; } case FrameworkStatsLog.OEM_MANAGED_BYTES_TRANSFER: { - ret.addAll(getDataUsageBytesTransferSnapshotForOemManaged()); + ret.addAll(getDataUsageBytesTransferSnapshotForOemManagedLocked()); break; } default: @@ -1325,8 +1341,9 @@ public class StatsPullAtomService extends SystemService { return ret; } + @GuardedBy("mDataBytesTransferLock") private int pullDataBytesTransferLocked(int atomTag, @NonNull List<StatsEvent> pulledData) { - final List<NetworkStatsExt> current = collectNetworkStatsSnapshotForAtom(atomTag); + final List<NetworkStatsExt> current = collectNetworkStatsSnapshotForAtomLocked(atomTag); if (current == null) { Slog.e(TAG, "current snapshot is null for " + atomTag + ", return."); @@ -1459,8 +1476,9 @@ public class StatsPullAtomService extends SystemService { } } + @GuardedBy("mDataBytesTransferLock") @NonNull - private List<NetworkStatsExt> getDataUsageBytesTransferSnapshotForOemManaged() { + private List<NetworkStatsExt> getDataUsageBytesTransferSnapshotForOemManagedLocked() { final List<Pair<Integer, Integer>> matchRulesAndTransports = List.of( new Pair(MATCH_ETHERNET, TRANSPORT_ETHERNET), new Pair(MATCH_MOBILE, TRANSPORT_CELLULAR), @@ -1479,7 +1497,8 @@ public class StatsPullAtomService extends SystemService { // Thus, specifying networks through their identifiers are not needed. final NetworkTemplate template = new NetworkTemplate.Builder(matchRule) .setOemManaged(oemManaged).build(); - final NetworkStats stats = getUidNetworkStatsSnapshotForTemplate(template, false); + final NetworkStats stats = getUidNetworkStatsSnapshotForTemplateLocked( + template, false); final Integer transport = ruleAndTransport.second; if (stats != null) { ret.add(new NetworkStatsExt(sliceNetworkStatsByUidAndFgbg(stats), @@ -1496,8 +1515,9 @@ public class StatsPullAtomService extends SystemService { /** * Create a snapshot of NetworkStats for a given transport. */ + @GuardedBy("mDataBytesTransferLock") @Nullable - private NetworkStats getUidNetworkStatsSnapshotForTransport(int transport) { + private NetworkStats getUidNetworkStatsSnapshotForTransportLocked(int transport) { NetworkTemplate template = null; switch (transport) { case TRANSPORT_CELLULAR: @@ -1510,7 +1530,7 @@ public class StatsPullAtomService extends SystemService { default: Log.wtf(TAG, "Unexpected transport."); } - return getUidNetworkStatsSnapshotForTemplate(template, /*includeTags=*/false); + return getUidNetworkStatsSnapshotForTemplateLocked(template, /*includeTags=*/false); } /** @@ -1534,8 +1554,9 @@ public class StatsPullAtomService extends SystemService { * Note that this should be only used to calculate diff since the snapshot might contains * some traffic before boot. */ + @GuardedBy("mDataBytesTransferLock") @Nullable - private NetworkStats getUidNetworkStatsSnapshotForTemplate( + private NetworkStats getUidNetworkStatsSnapshotForTemplateLocked( @NonNull NetworkTemplate template, boolean includeTags) { final long elapsedMillisSinceBoot = SystemClock.elapsedRealtime(); final long currentTimeInMillis = MICROSECONDS.toMillis(SystemClock.currentTimeMicro()); @@ -1547,13 +1568,19 @@ public class StatsPullAtomService extends SystemService { final long startTime = currentTimeInMillis - elapsedMillisSinceBoot - bucketDuration; final long endTime = currentTimeInMillis + bucketDuration; - // TODO (b/156313635): This is short-term hack to allow perfd gets updated networkStats - // history when query in every second in order to show realtime statistics. However, - // this is not a good long-term solution since NetworkStatsService will make frequent - // I/O and also block main thread when polling. - // Consider making perfd queries NetworkStatsService directly. - if (template.getMatchRule() == MATCH_WIFI && template.getSubscriberIds().isEmpty()) { - getNetworkStatsManager().forceUpdate(); + // NetworkStatsManager#forceUpdate updates stats for all networks + if (applyNetworkStatsPollRateLimit()) { + // The new way: rate-limit force-polling for all NetworkStats queries + if (elapsedMillisSinceBoot - mLastNetworkStatsPollTime >= NETSTATS_POLL_RATE_LIMIT_MS) { + mLastNetworkStatsPollTime = elapsedMillisSinceBoot; + getNetworkStatsManager().forceUpdate(); + } + } else { + // The old way: force-poll only on WiFi queries. Data for other queries can be stale + // if there was no recent poll beforehand (e.g. for WiFi or scheduled poll) + if (template.getMatchRule() == MATCH_WIFI && template.getSubscriberIds().isEmpty()) { + getNetworkStatsManager().forceUpdate(); + } } final android.app.usage.NetworkStats queryNonTaggedStats = @@ -1572,8 +1599,9 @@ public class StatsPullAtomService extends SystemService { return nonTaggedStats.add(taggedStats); } + @GuardedBy("mDataBytesTransferLock") @NonNull - private List<NetworkStatsExt> getDataUsageBytesTransferSnapshotForSub( + private List<NetworkStatsExt> getDataUsageBytesTransferSnapshotForSubLocked( @NonNull SubInfo subInfo) { final List<NetworkStatsExt> ret = new ArrayList<>(); for (final int ratType : getAllCollapsedRatTypes()) { @@ -1583,7 +1611,7 @@ public class StatsPullAtomService extends SystemService { .setRatType(ratType) .setMeteredness(METERED_YES).build(); final NetworkStats stats = - getUidNetworkStatsSnapshotForTemplate(template, /*includeTags=*/false); + getUidNetworkStatsSnapshotForTemplateLocked(template, /*includeTags=*/false); if (stats != null) { ret.add(new NetworkStatsExt(sliceNetworkStatsByFgbg(stats), new int[]{TRANSPORT_CELLULAR}, /*slicedByFgbg=*/true, @@ -5273,6 +5301,13 @@ public class StatsPullAtomService extends SystemService { @Override public void onSubscriptionsChanged() { + synchronized (mDataBytesTransferLock) { + onSubscriptionsChangedLocked(); + } + } + + @GuardedBy("mDataBytesTransferLock") + private void onSubscriptionsChangedLocked() { final List<SubscriptionInfo> currentSubs = mSm.getCompleteActiveSubscriptionInfoList(); for (final SubscriptionInfo sub : currentSubs) { final SubInfo match = CollectionUtils.find(mHistoricalSubs, @@ -5295,12 +5330,11 @@ public class StatsPullAtomService extends SystemService { subscriberId, sub.isOpportunistic()); Slog.i(TAG, "subId " + subId + " added into historical sub list"); - synchronized (mDataBytesTransferLock) { - mHistoricalSubs.add(subInfo); - // Since getting snapshot when pulling will also include data before boot, - // query stats as baseline to prevent double count is needed. - mNetworkStatsBaselines.addAll(getDataUsageBytesTransferSnapshotForSub(subInfo)); - } + mHistoricalSubs.add(subInfo); + // Since getting snapshot when pulling will also include data before boot, + // query stats as baseline to prevent double count is needed. + mNetworkStatsBaselines.addAll( + getDataUsageBytesTransferSnapshotForSubLocked(subInfo)); } } } diff --git a/services/core/java/com/android/server/stats/stats_flags.aconfig b/services/core/java/com/android/server/stats/stats_flags.aconfig index 6faa2737ac30..f360837e1d28 100644 --- a/services/core/java/com/android/server/stats/stats_flags.aconfig +++ b/services/core/java/com/android/server/stats/stats_flags.aconfig @@ -8,3 +8,11 @@ flag { bug: "309512867" is_fixed_read_only: true } + +flag { + name: "apply_network_stats_poll_rate_limit" + namespace: "statsd" + description: "Apply a rate limit for polling network stats when pulling relevant atoms" + bug: "352495181" + is_fixed_read_only: true +} diff --git a/services/core/java/com/android/server/statusbar/StatusBarManagerService.java b/services/core/java/com/android/server/statusbar/StatusBarManagerService.java index 85c8900555d9..e9423ce48624 100644 --- a/services/core/java/com/android/server/statusbar/StatusBarManagerService.java +++ b/services/core/java/com/android/server/statusbar/StatusBarManagerService.java @@ -1890,8 +1890,7 @@ public class StatusBarManagerService extends IStatusBarService.Stub implements D enforceStatusBarService(); final long token = Binder.clearCallingIdentity(); try { - // TODO(b/308479256): Check if hiding "all" IMEs is OK or not. - InputMethodManagerInternal.get().hideAllInputMethods( + InputMethodManagerInternal.get().hideInputMethod( SoftInputShowHideReason.HIDE_BUBBLES, displayId); } finally { Binder.restoreCallingIdentity(token); diff --git a/services/core/java/com/android/server/timezonedetector/location/ZoneInfoDbTimeZoneProviderEventPreProcessor.java b/services/core/java/com/android/server/timezonedetector/location/ZoneInfoDbTimeZoneProviderEventPreProcessor.java index aa2b74edaff2..58c3ba5013fa 100644 --- a/services/core/java/com/android/server/timezonedetector/location/ZoneInfoDbTimeZoneProviderEventPreProcessor.java +++ b/services/core/java/com/android/server/timezonedetector/location/ZoneInfoDbTimeZoneProviderEventPreProcessor.java @@ -56,12 +56,17 @@ public class ZoneInfoDbTimeZoneProviderEventPreProcessor // enables immediate failover to a secondary provider, one that might provide valid IDs for // the same location, which should provide better behavior than just ignoring the event. if (hasInvalidZones(event)) { - TimeZoneProviderStatus providerStatus = new TimeZoneProviderStatus.Builder( - event.getTimeZoneProviderStatus()) - .setTimeZoneResolutionOperationStatus(OPERATION_STATUS_FAILED) - .build(); - return TimeZoneProviderEvent.createUncertainEvent( - event.getCreationElapsedMillis(), providerStatus); + TimeZoneProviderStatus providerStatus = event.getTimeZoneProviderStatus(); + TimeZoneProviderStatus.Builder providerStatusBuilder; + if (providerStatus != null) { + providerStatusBuilder = new TimeZoneProviderStatus.Builder(providerStatus); + } else { + providerStatusBuilder = new TimeZoneProviderStatus.Builder(); + } + return TimeZoneProviderEvent.createUncertainEvent(event.getCreationElapsedMillis(), + providerStatusBuilder + .setTimeZoneResolutionOperationStatus(OPERATION_STATUS_FAILED) + .build()); } return event; diff --git a/services/core/java/com/android/server/vibrator/HalVibration.java b/services/core/java/com/android/server/vibrator/HalVibration.java index f9bad59d38b0..46bd7af159da 100644 --- a/services/core/java/com/android/server/vibrator/HalVibration.java +++ b/services/core/java/com/android/server/vibrator/HalVibration.java @@ -108,23 +108,6 @@ final class HalVibration extends Vibration { } /** - * Resolves the default vibration amplitude of {@link #getEffectToPlay()} and each fallback. - * - * @param defaultAmplitude An integer in [1,255] representing the device default amplitude to - * replace the {@link VibrationEffect#DEFAULT_AMPLITUDE}. - */ - public void resolveEffects(int defaultAmplitude) { - CombinedVibration newEffect = - mEffectToPlay.transform(VibrationEffect::resolve, defaultAmplitude); - if (!Objects.equals(mEffectToPlay, newEffect)) { - mEffectToPlay = newEffect; - } - for (int i = 0; i < mFallbacks.size(); i++) { - mFallbacks.setValueAt(i, mFallbacks.valueAt(i).resolve(defaultAmplitude)); - } - } - - /** * Scales the {@link #getEffectToPlay()} and each fallback effect based on the vibration usage. */ public void scaleEffects(VibrationScaler scaler) { diff --git a/services/core/java/com/android/server/vibrator/HapticFeedbackVibrationProvider.java b/services/core/java/com/android/server/vibrator/HapticFeedbackVibrationProvider.java index 98a2ba0d62cf..3f9da82e3d2e 100644 --- a/services/core/java/com/android/server/vibrator/HapticFeedbackVibrationProvider.java +++ b/services/core/java/com/android/server/vibrator/HapticFeedbackVibrationProvider.java @@ -46,6 +46,8 @@ public final class HapticFeedbackVibrationProvider { VibrationAttributes.createForUsage(VibrationAttributes.USAGE_HARDWARE_FEEDBACK); private static final VibrationAttributes COMMUNICATION_REQUEST_VIBRATION_ATTRIBUTES = VibrationAttributes.createForUsage(VibrationAttributes.USAGE_COMMUNICATION_REQUEST); + private static final VibrationAttributes IME_FEEDBACK_VIBRATION_ATTRIBUTES = + VibrationAttributes.createForUsage(VibrationAttributes.USAGE_IME_FEEDBACK); private final VibratorInfo mVibratorInfo; private final boolean mHapticTextHandleEnabled; @@ -219,8 +221,6 @@ public final class HapticFeedbackVibrationProvider { } int vibFlags = 0; - boolean fromIme = - (privFlags & HapticFeedbackConstants.PRIVATE_FLAG_APPLY_INPUT_METHOD_SETTINGS) != 0; boolean bypassVibrationIntensitySetting = (flags & HapticFeedbackConstants.FLAG_IGNORE_GLOBAL_SETTING) != 0; if (bypassVibrationIntensitySetting) { @@ -229,9 +229,6 @@ public final class HapticFeedbackVibrationProvider { if (shouldBypassInterruptionPolicy(effectId)) { vibFlags |= VibrationAttributes.FLAG_BYPASS_INTERRUPTION_POLICY; } - if (shouldBypassIntensityScale(effectId, fromIme)) { - vibFlags |= VibrationAttributes.FLAG_BYPASS_USER_VIBRATION_INTENSITY_SCALE; - } return vibFlags == 0 ? attrs : new VibrationAttributes.Builder(attrs) .setFlags(vibFlags).build(); @@ -362,22 +359,6 @@ public final class HapticFeedbackVibrationProvider { /* fallbackForPredefinedEffect= */ predefinedEffectFallback); } - private boolean shouldBypassIntensityScale(int effectId, boolean isIme) { - if (!Flags.keyboardCategoryEnabled() || mKeyboardVibrationFixedAmplitude < 0 || !isIme) { - // Shouldn't bypass if not support keyboard category, no fixed amplitude or not an IME. - return false; - } - switch (effectId) { - case HapticFeedbackConstants.KEYBOARD_TAP: - return mVibratorInfo.isPrimitiveSupported( - VibrationEffect.Composition.PRIMITIVE_CLICK); - case HapticFeedbackConstants.KEYBOARD_RELEASE: - return mVibratorInfo.isPrimitiveSupported( - VibrationEffect.Composition.PRIMITIVE_TICK); - } - return false; - } - private VibrationAttributes createKeyboardVibrationAttributes( @HapticFeedbackConstants.PrivateFlags int privFlags) { // Use touch attribute when the keyboard category is disable. @@ -388,7 +369,8 @@ public final class HapticFeedbackVibrationProvider { if ((privFlags & HapticFeedbackConstants.PRIVATE_FLAG_APPLY_INPUT_METHOD_SETTINGS) == 0) { return TOUCH_VIBRATION_ATTRIBUTES; } - return new VibrationAttributes.Builder(TOUCH_VIBRATION_ATTRIBUTES) + return new VibrationAttributes.Builder(IME_FEEDBACK_VIBRATION_ATTRIBUTES) + // TODO(b/332661766): Remove CATEGORY_KEYBOARD logic .setCategory(VibrationAttributes.CATEGORY_KEYBOARD) .build(); } diff --git a/services/core/java/com/android/server/vibrator/VibrationSettings.java b/services/core/java/com/android/server/vibrator/VibrationSettings.java index 02061555a37f..fb92d609f1cf 100644 --- a/services/core/java/com/android/server/vibrator/VibrationSettings.java +++ b/services/core/java/com/android/server/vibrator/VibrationSettings.java @@ -21,6 +21,7 @@ import static android.os.VibrationAttributes.USAGE_ACCESSIBILITY; import static android.os.VibrationAttributes.USAGE_ALARM; import static android.os.VibrationAttributes.USAGE_COMMUNICATION_REQUEST; import static android.os.VibrationAttributes.USAGE_HARDWARE_FEEDBACK; +import static android.os.VibrationAttributes.USAGE_IME_FEEDBACK; import static android.os.VibrationAttributes.USAGE_MEDIA; import static android.os.VibrationAttributes.USAGE_NOTIFICATION; import static android.os.VibrationAttributes.USAGE_PHYSICAL_EMULATION; @@ -560,6 +561,7 @@ final class VibrationSettings { mKeyboardVibrationOn = loadSystemSetting( Settings.System.KEYBOARD_VIBRATION_ENABLED, 1, userHandle) > 0; + int keyboardIntensity = getDefaultIntensity(USAGE_IME_FEEDBACK); int alarmIntensity = toIntensity( loadSystemSetting(Settings.System.ALARM_VIBRATION_INTENSITY, -1, userHandle), getDefaultIntensity(USAGE_ALARM)); @@ -610,6 +612,12 @@ final class VibrationSettings { mCurrentVibrationIntensities.put(USAGE_TOUCH, hapticFeedbackIntensity); } + if (mVibrationConfig.isKeyboardVibrationSettingsSupported()) { + mCurrentVibrationIntensities.put(USAGE_IME_FEEDBACK, keyboardIntensity); + } else { + mCurrentVibrationIntensities.put(USAGE_IME_FEEDBACK, hapticFeedbackIntensity); + } + // A11y is not disabled by any haptic feedback setting. mCurrentVibrationIntensities.put(USAGE_ACCESSIBILITY, positiveHapticFeedbackIntensity); } diff --git a/services/core/java/com/android/server/vibrator/VibrationStepConductor.java b/services/core/java/com/android/server/vibrator/VibrationStepConductor.java index 8c9a92de03a9..7152844cc772 100644 --- a/services/core/java/com/android/server/vibrator/VibrationStepConductor.java +++ b/services/core/java/com/android/server/vibrator/VibrationStepConductor.java @@ -21,7 +21,6 @@ import android.annotation.Nullable; import android.os.Build; import android.os.CombinedVibration; import android.os.IBinder; -import android.os.VibrationAttributes; import android.os.VibrationEffect; import android.os.vibrator.Flags; import android.os.vibrator.PrebakedSegment; @@ -177,16 +176,11 @@ final class VibrationStepConductor implements IBinder.DeathRecipient { expectIsVibrationThread(true); } - if (!mVibration.callerInfo.attrs.isFlagSet( - VibrationAttributes.FLAG_BYPASS_USER_VIBRATION_INTENSITY_SCALE)) { - if (Flags.adaptiveHapticsEnabled()) { - waitForVibrationParamsIfRequired(); - } - // Scale resolves the default amplitudes from the effect before scaling them. - mVibration.scaleEffects(mVibrationScaler); - } else { - mVibration.resolveEffects(mVibrationScaler.getDefaultVibrationAmplitude()); + if (Flags.adaptiveHapticsEnabled()) { + waitForVibrationParamsIfRequired(); } + // Scale resolves the default amplitudes from the effect before scaling them. + mVibration.scaleEffects(mVibrationScaler); mVibration.adaptToDevice(mDeviceAdapter); CombinedVibration.Sequential sequentialEffect = toSequential(mVibration.getEffectToPlay()); diff --git a/services/core/java/com/android/server/vibrator/VibratorControlService.java b/services/core/java/com/android/server/vibrator/VibratorControlService.java index 4da6585a57aa..de5e662f2a71 100644 --- a/services/core/java/com/android/server/vibrator/VibratorControlService.java +++ b/services/core/java/com/android/server/vibrator/VibratorControlService.java @@ -41,6 +41,7 @@ import android.os.RemoteException; import android.os.SystemClock; import android.os.VibrationAttributes; import android.os.VibrationEffect; +import android.os.vibrator.Flags; import android.util.IndentingPrintWriter; import android.util.IntArray; import android.util.Slog; @@ -265,9 +266,15 @@ final class VibratorControlService extends IVibratorControlService.Stub { return null; } + if (Flags.throttleVibrationParamsRequests() && mVibrationParamRequest != null + && mVibrationParamRequest.usage == usage) { + // Reuse existing future for ongoing request with same usage. + return mVibrationParamRequest.future; + } + try { endOngoingRequestVibrationParamsLocked(/* wasCancelled= */ true); - mVibrationParamRequest = new VibrationParamRequest(uid); + mVibrationParamRequest = new VibrationParamRequest(uid, usage); vibratorController.requestVibrationParams(vibrationType, timeoutInMillis, mVibrationParamRequest.token); return mVibrationParamRequest.future; @@ -533,10 +540,12 @@ final class VibratorControlService extends IVibratorControlService.Stub { public final CompletableFuture<Void> future = new CompletableFuture<>(); public final IBinder token = new Binder(); public final int uid; + public final @VibrationAttributes.Usage int usage; public final long uptimeMs; - VibrationParamRequest(int uid) { + VibrationParamRequest(int uid, @VibrationAttributes.Usage int usage) { this.uid = uid; + this.usage = usage; uptimeMs = SystemClock.uptimeMillis(); } diff --git a/services/core/java/com/android/server/vibrator/VibratorManagerService.java b/services/core/java/com/android/server/vibrator/VibratorManagerService.java index 48c4a68250b1..7610d7d6b659 100644 --- a/services/core/java/com/android/server/vibrator/VibratorManagerService.java +++ b/services/core/java/com/android/server/vibrator/VibratorManagerService.java @@ -103,8 +103,7 @@ public class VibratorManagerService extends IVibratorManagerService.Stub { new VibrationAttributes.Builder().build(); private static final int ATTRIBUTES_ALL_BYPASS_FLAGS = VibrationAttributes.FLAG_BYPASS_INTERRUPTION_POLICY - | VibrationAttributes.FLAG_BYPASS_USER_VIBRATION_INTENSITY_OFF - | VibrationAttributes.FLAG_BYPASS_USER_VIBRATION_INTENSITY_SCALE; + | VibrationAttributes.FLAG_BYPASS_USER_VIBRATION_INTENSITY_OFF; /** Fixed large duration used to note repeating vibrations to {@link IBatteryStats}. */ private static final long BATTERY_STATS_REPEATING_VIBRATION_DURATION = 5_000; @@ -925,8 +924,7 @@ public class VibratorManagerService extends IVibratorManagerService.Stub { private VibrationStepConductor createVibrationStepConductor(HalVibration vib) { CompletableFuture<Void> requestVibrationParamsFuture = null; - if (Flags.adaptiveHapticsEnabled() && !vib.callerInfo.attrs.isFlagSet( - VibrationAttributes.FLAG_BYPASS_USER_VIBRATION_INTENSITY_SCALE) + if (Flags.adaptiveHapticsEnabled() && mVibratorControlService.shouldRequestVibrationParams( vib.callerInfo.attrs.getUsage())) { requestVibrationParamsFuture = @@ -940,13 +938,8 @@ public class VibratorManagerService extends IVibratorManagerService.Stub { } private Vibration.EndInfo startVibrationOnInputDevicesLocked(HalVibration vib) { - if (!vib.callerInfo.attrs.isFlagSet( - VibrationAttributes.FLAG_BYPASS_USER_VIBRATION_INTENSITY_SCALE)) { - // Scale resolves the default amplitudes from the effect before scaling them. - vib.scaleEffects(mVibrationScaler); - } else { - vib.resolveEffects(mVibrationScaler.getDefaultVibrationAmplitude()); - } + // Scale resolves the default amplitudes from the effect before scaling them. + vib.scaleEffects(mVibrationScaler); mInputDeviceDelegate.vibrateIfAvailable(vib.callerInfo, vib.getEffectToPlay()); return new Vibration.EndInfo(Vibration.Status.FORWARDED_TO_INPUT_DEVICES); diff --git a/services/core/java/com/android/server/wallpaper/WallpaperCropper.java b/services/core/java/com/android/server/wallpaper/WallpaperCropper.java index f70a3ba107e1..d5bea4adaf8c 100644 --- a/services/core/java/com/android/server/wallpaper/WallpaperCropper.java +++ b/services/core/java/com/android/server/wallpaper/WallpaperCropper.java @@ -676,7 +676,12 @@ public class WallpaperCropper { final Rect estimateCrop = new Rect(cropHint); if (!multiCrop()) estimateCrop.scale(1f / options.inSampleSize); - else estimateCrop.scale(1f / sampleSize); + else { + estimateCrop.left = (int) Math.floor(estimateCrop.left / sampleSize); + estimateCrop.top = (int) Math.floor(estimateCrop.top / sampleSize); + estimateCrop.right = (int) Math.ceil(estimateCrop.right / sampleSize); + estimateCrop.bottom = (int) Math.ceil(estimateCrop.bottom / sampleSize); + } float hRatio = (float) wpData.mHeight / estimateCrop.height(); final int destHeight = (int) (estimateCrop.height() * hRatio); final int destWidth = (int) (estimateCrop.width() * hRatio); @@ -720,7 +725,10 @@ public class WallpaperCropper { } if (multiCrop()) { Slog.v(TAG, " cropHint=" + cropHint); + Slog.v(TAG, " estimateCrop=" + estimateCrop); Slog.v(TAG, " sampleSize=" + sampleSize); + Slog.v(TAG, " user defined crops: " + wallpaper.mCropHints); + Slog.v(TAG, " all crops: " + defaultCrops); } Slog.v(TAG, " targetSize=" + safeWidth + "x" + safeHeight); Slog.v(TAG, " maxTextureSize=" + GLHelper.getMaxTextureSize()); diff --git a/services/core/java/com/android/server/wm/ActivityClientController.java b/services/core/java/com/android/server/wm/ActivityClientController.java index 023dd79d391b..0c10551a9b23 100644 --- a/services/core/java/com/android/server/wm/ActivityClientController.java +++ b/services/core/java/com/android/server/wm/ActivityClientController.java @@ -68,7 +68,6 @@ import android.app.ActivityManager; import android.app.ActivityTaskManager; import android.app.FullscreenRequestHandler; import android.app.IActivityClientController; -import android.app.ICompatCameraControlCallback; import android.app.IRequestFinishCallback; import android.app.PictureInPictureParams; import android.app.PictureInPictureUiState; @@ -1008,22 +1007,6 @@ class ActivityClientController extends IActivityClientController.Stub { Binder.restoreCallingIdentity(origId); } - @Override - public void requestCompatCameraControl(IBinder token, boolean showControl, - boolean transformationApplied, ICompatCameraControlCallback callback) { - final long origId = Binder.clearCallingIdentity(); - try { - synchronized (mGlobalLock) { - final ActivityRecord r = ActivityRecord.isInRootTaskLocked(token); - if (r != null) { - r.updateCameraCompatState(showControl, transformationApplied, callback); - } - } - } finally { - Binder.restoreCallingIdentity(origId); - } - } - /** * Initialize the {@link #mSetPipAspectRatioQuotaTracker} if applicable, which should happen * out of {@link #mGlobalLock} to avoid deadlock (AM lock is used in QuotaTrack ctor). diff --git a/services/core/java/com/android/server/wm/ActivityMetricsLogger.java b/services/core/java/com/android/server/wm/ActivityMetricsLogger.java index b3208bfcc93d..4085ec90c95e 100644 --- a/services/core/java/com/android/server/wm/ActivityMetricsLogger.java +++ b/services/core/java/com/android/server/wm/ActivityMetricsLogger.java @@ -4,10 +4,6 @@ import static android.app.ActivityManager.PROCESS_STATE_NONEXISTENT; import static android.app.ActivityManager.START_SUCCESS; import static android.app.ActivityManager.START_TASK_TO_FRONT; import static android.app.ActivityManager.processStateAmToProto; -import static android.app.CameraCompatTaskInfo.CAMERA_COMPAT_CONTROL_DISMISSED; -import static android.app.CameraCompatTaskInfo.CAMERA_COMPAT_CONTROL_HIDDEN; -import static android.app.CameraCompatTaskInfo.CAMERA_COMPAT_CONTROL_TREATMENT_APPLIED; -import static android.app.CameraCompatTaskInfo.CAMERA_COMPAT_CONTROL_TREATMENT_SUGGESTED; import static android.app.WaitResult.INVALID_DELAY; import static android.app.WaitResult.LAUNCH_STATE_COLD; import static android.app.WaitResult.LAUNCH_STATE_HOT; @@ -69,11 +65,6 @@ import static com.android.internal.util.FrameworkStatsLog.APP_COMPAT_STATE_CHANG import static com.android.internal.util.FrameworkStatsLog.APP_COMPAT_STATE_CHANGED__STATE__NOT_VISIBLE; import static com.android.internal.util.FrameworkStatsLog.APP_START_OCCURRED__PACKAGE_STOPPED_STATE__PACKAGE_STATE_NORMAL; import static com.android.internal.util.FrameworkStatsLog.APP_START_OCCURRED__PACKAGE_STOPPED_STATE__PACKAGE_STATE_STOPPED; -import static com.android.internal.util.FrameworkStatsLog.CAMERA_COMPAT_CONTROL_EVENT_REPORTED__EVENT__APPEARED_APPLY_TREATMENT; -import static com.android.internal.util.FrameworkStatsLog.CAMERA_COMPAT_CONTROL_EVENT_REPORTED__EVENT__APPEARED_REVERT_TREATMENT; -import static com.android.internal.util.FrameworkStatsLog.CAMERA_COMPAT_CONTROL_EVENT_REPORTED__EVENT__CLICKED_APPLY_TREATMENT; -import static com.android.internal.util.FrameworkStatsLog.CAMERA_COMPAT_CONTROL_EVENT_REPORTED__EVENT__CLICKED_DISMISS; -import static com.android.internal.util.FrameworkStatsLog.CAMERA_COMPAT_CONTROL_EVENT_REPORTED__EVENT__CLICKED_REVERT_TREATMENT; import static com.android.server.am.MemoryStatUtil.MemoryStat; import static com.android.server.am.MemoryStatUtil.readMemoryStatFromFilesystem; import static com.android.server.am.ProcessList.INVALID_ADJ; @@ -89,7 +80,6 @@ import android.annotation.Nullable; import android.app.ActivityOptions; import android.app.ActivityOptions.SourceInfo; import android.app.ApplicationStartInfo; -import android.app.CameraCompatTaskInfo.CameraCompatControlState; import android.app.WaitResult; import android.app.WindowConfiguration.WindowingMode; import android.content.ComponentName; @@ -1662,71 +1652,6 @@ class ActivityMetricsLogger { } } - /** - * Logs the Camera Compat Control appeared event that corresponds to the given {@code state} - * with the given {@code packageUid}. - */ - void logCameraCompatControlAppearedEventReported(@CameraCompatControlState int state, - int packageUid) { - switch (state) { - case CAMERA_COMPAT_CONTROL_TREATMENT_SUGGESTED: - logCameraCompatControlEventReported( - CAMERA_COMPAT_CONTROL_EVENT_REPORTED__EVENT__APPEARED_APPLY_TREATMENT, - packageUid); - break; - case CAMERA_COMPAT_CONTROL_TREATMENT_APPLIED: - logCameraCompatControlEventReported( - CAMERA_COMPAT_CONTROL_EVENT_REPORTED__EVENT__APPEARED_REVERT_TREATMENT, - packageUid); - break; - case CAMERA_COMPAT_CONTROL_HIDDEN: - // Nothing to log. - break; - default: - Slog.w(TAG, "Unexpected state in logCameraCompatControlAppearedEventReported: " - + state); - break; - } - } - - /** - * Logs the Camera Compat Control clicked event that corresponds to the given {@code state} - * with the given {@code packageUid}. - */ - void logCameraCompatControlClickedEventReported(@CameraCompatControlState int state, - int packageUid) { - switch (state) { - case CAMERA_COMPAT_CONTROL_TREATMENT_APPLIED: - logCameraCompatControlEventReported( - CAMERA_COMPAT_CONTROL_EVENT_REPORTED__EVENT__CLICKED_APPLY_TREATMENT, - packageUid); - break; - case CAMERA_COMPAT_CONTROL_TREATMENT_SUGGESTED: - logCameraCompatControlEventReported( - CAMERA_COMPAT_CONTROL_EVENT_REPORTED__EVENT__CLICKED_REVERT_TREATMENT, - packageUid); - break; - case CAMERA_COMPAT_CONTROL_DISMISSED: - logCameraCompatControlEventReported( - CAMERA_COMPAT_CONTROL_EVENT_REPORTED__EVENT__CLICKED_DISMISS, - packageUid); - break; - default: - Slog.w(TAG, "Unexpected state in logCameraCompatControlAppearedEventReported: " - + state); - break; - } - } - - private void logCameraCompatControlEventReported(int event, int packageUid) { - FrameworkStatsLog.write(FrameworkStatsLog.CAMERA_COMPAT_CONTROL_EVENT_REPORTED, packageUid, - event); - if (DEBUG_METRICS) { - Slog.i(TAG, String.format("CAMERA_COMPAT_CONTROL_EVENT_REPORTED(%s, %s)", packageUid, - event)); - } - } - private ArtManagerInternal getArtManagerInternal() { if (mArtManagerInternal == null) { // Note that this may be null. diff --git a/services/core/java/com/android/server/wm/ActivityRecord.java b/services/core/java/com/android/server/wm/ActivityRecord.java index 7d70ea13f12c..8a768c0ed84d 100644 --- a/services/core/java/com/android/server/wm/ActivityRecord.java +++ b/services/core/java/com/android/server/wm/ActivityRecord.java @@ -33,12 +33,7 @@ import static android.app.ActivityOptions.ANIM_UNDEFINED; import static android.app.ActivityTaskManager.INVALID_TASK_ID; import static android.app.AppOpsManager.MODE_ALLOWED; import static android.app.AppOpsManager.OP_PICTURE_IN_PICTURE; -import static android.app.CameraCompatTaskInfo.CAMERA_COMPAT_CONTROL_DISMISSED; -import static android.app.CameraCompatTaskInfo.CAMERA_COMPAT_CONTROL_HIDDEN; -import static android.app.CameraCompatTaskInfo.CAMERA_COMPAT_CONTROL_TREATMENT_APPLIED; -import static android.app.CameraCompatTaskInfo.CAMERA_COMPAT_CONTROL_TREATMENT_SUGGESTED; import static android.app.CameraCompatTaskInfo.CAMERA_COMPAT_FREEFORM_NONE; -import static android.app.CameraCompatTaskInfo.cameraCompatControlStateToString; import static android.app.WaitResult.INVALID_DELAY; import static android.app.WindowConfiguration.ACTIVITY_TYPE_ASSISTANT; import static android.app.WindowConfiguration.ACTIVITY_TYPE_DREAM; @@ -271,8 +266,6 @@ import android.annotation.Size; import android.app.Activity; import android.app.ActivityManager.TaskDescription; import android.app.ActivityOptions; -import android.app.CameraCompatTaskInfo.CameraCompatControlState; -import android.app.ICompatCameraControlCallback; import android.app.IScreenCaptureObserver; import android.app.PendingIntent; import android.app.PictureInPictureParams; @@ -371,6 +364,7 @@ import android.window.WindowOnBackInvokedDispatcher; import com.android.internal.R; import com.android.internal.annotations.GuardedBy; +import com.android.internal.annotations.KeepForWeakReference; import com.android.internal.annotations.VisibleForTesting; import com.android.internal.app.ResolverActivity; import com.android.internal.content.ReferrerIntent; @@ -824,19 +818,6 @@ final class ActivityRecord extends WindowToken implements WindowManagerService.A // and therefore #isLetterboxedForFixedOrientationAndAspectRatio returns false. private boolean mIsEligibleForFixedOrientationLetterbox; - // State of the Camera app compat control which is used to correct stretched viewfinder - // in apps that don't handle all possible configurations and changes between them correctly. - @CameraCompatControlState - private int mCameraCompatControlState = CAMERA_COMPAT_CONTROL_HIDDEN; - - // The callback that allows to ask the calling View to apply the treatment for stretched - // issues affecting camera viewfinders when the user clicks on the camera compat control. - @Nullable - private ICompatCameraControlCallback mCompatCameraControlCallback; - - private final boolean mCameraCompatControlEnabled; - private boolean mCameraCompatControlClickedByUser; - // activity is not displayed? // TODO: rename to mNoDisplay @VisibleForTesting @@ -941,6 +922,8 @@ final class ActivityRecord extends WindowToken implements WindowManagerService.A private RemoteCallbackList<IScreenCaptureObserver> mCaptureCallbacks; + // Ensure the field is kept during optimization to preserve downstream weak refs. + @KeepForWeakReference private final ColorDisplayService.ColorTransformController mColorTransformController = (matrix, translation) -> mWmService.mH.post(() -> { synchronized (mWmService.mGlobalLock) { @@ -1342,10 +1325,6 @@ final class ActivityRecord extends WindowToken implements WindowManagerService.A } mLetterboxUiController.dump(pw, prefix); - - pw.println(prefix + "mCameraCompatControlState=" - + cameraCompatControlStateToString(mCameraCompatControlState)); - pw.println(prefix + "mCameraCompatControlEnabled=" + mCameraCompatControlEnabled); } static boolean dumpActivity(FileDescriptor fd, PrintWriter pw, int index, ActivityRecord r, @@ -1884,100 +1863,6 @@ final class ActivityRecord extends WindowToken implements WindowManagerService.A mLetterboxUiController.getLetterboxInnerBounds(outBounds); } - void updateCameraCompatState(boolean showControl, boolean transformationApplied, - ICompatCameraControlCallback callback) { - if (!isCameraCompatControlEnabled()) { - // Feature is disabled by config_isCameraCompatControlForStretchedIssuesEnabled. - return; - } - if (mCameraCompatControlClickedByUser && (showControl - || mCameraCompatControlState == CAMERA_COMPAT_CONTROL_DISMISSED)) { - // The user already applied treatment on this activity or dismissed control. - // Respecting their choice. - return; - } - mCompatCameraControlCallback = callback; - int newCameraCompatControlState = !showControl - ? CAMERA_COMPAT_CONTROL_HIDDEN - : transformationApplied - ? CAMERA_COMPAT_CONTROL_TREATMENT_APPLIED - : CAMERA_COMPAT_CONTROL_TREATMENT_SUGGESTED; - boolean changed = setCameraCompatControlState(newCameraCompatControlState); - if (!changed) { - return; - } - mTaskSupervisor.getActivityMetricsLogger().logCameraCompatControlAppearedEventReported( - newCameraCompatControlState, info.applicationInfo.uid); - if (newCameraCompatControlState == CAMERA_COMPAT_CONTROL_HIDDEN) { - mCameraCompatControlClickedByUser = false; - mCompatCameraControlCallback = null; - } - // Trigger TaskInfoChanged to update the camera compat UI. - getTask().dispatchTaskInfoChangedIfNeeded(true /* force */); - // TaskOrganizerController#onTaskInfoChanged adds pending task events to the queue waiting - // for the surface placement to be ready. So need to trigger surface placement to dispatch - // events to avoid stale state for the camera compat control. - getDisplayContent().setLayoutNeeded(); - mWmService.mWindowPlacerLocked.performSurfacePlacement(); - } - - void updateCameraCompatStateFromUser(@CameraCompatControlState int state) { - if (!isCameraCompatControlEnabled()) { - // Feature is disabled by config_isCameraCompatControlForStretchedIssuesEnabled. - return; - } - if (state == CAMERA_COMPAT_CONTROL_HIDDEN) { - Slog.w(TAG, "Unexpected hidden state in updateCameraCompatState"); - return; - } - boolean changed = setCameraCompatControlState(state); - mCameraCompatControlClickedByUser = true; - if (!changed) { - return; - } - mTaskSupervisor.getActivityMetricsLogger().logCameraCompatControlClickedEventReported( - state, info.applicationInfo.uid); - if (state == CAMERA_COMPAT_CONTROL_DISMISSED) { - mCompatCameraControlCallback = null; - return; - } - if (mCompatCameraControlCallback == null) { - Slog.w(TAG, "Callback for a camera compat control is null"); - return; - } - try { - if (state == CAMERA_COMPAT_CONTROL_TREATMENT_APPLIED) { - mCompatCameraControlCallback.applyCameraCompatTreatment(); - } else { - mCompatCameraControlCallback.revertCameraCompatTreatment(); - } - } catch (RemoteException e) { - Slog.e(TAG, "Unable to apply or revert camera compat treatment", e); - } - } - - private boolean setCameraCompatControlState(@CameraCompatControlState int state) { - if (!isCameraCompatControlEnabled()) { - // Feature is disabled by config_isCameraCompatControlForStretchedIssuesEnabled. - return false; - } - if (mCameraCompatControlState != state) { - mCameraCompatControlState = state; - return true; - } - return false; - } - - @CameraCompatControlState - int getCameraCompatControlState() { - return mCameraCompatControlState; - } - - @VisibleForTesting - boolean isCameraCompatControlEnabled() { - return mCameraCompatControlEnabled; - } - /** * @return {@code true} if bar shown within a given rectangle is allowed to be fully transparent * when the current activity is displayed. @@ -2105,8 +1990,6 @@ final class ActivityRecord extends WindowToken implements WindowManagerService.A // initialised. mLetterboxUiController = new LetterboxUiController(mWmService, this); mAppCompatController = new AppCompatController(mWmService, this); - mCameraCompatControlEnabled = mWmService.mContext.getResources() - .getBoolean(R.bool.config_isCameraCompatControlForStretchedIssuesEnabled); mResolveConfigHint = new TaskFragment.ConfigOverrideHint(); if (mWmService.mFlags.mInsetsDecoupledConfiguration) { // When the stable configuration is the default behavior, override for the legacy apps diff --git a/services/core/java/com/android/server/wm/ActivityTaskSupervisor.java b/services/core/java/com/android/server/wm/ActivityTaskSupervisor.java index afdbc0a6b43f..509a060c096d 100644 --- a/services/core/java/com/android/server/wm/ActivityTaskSupervisor.java +++ b/services/core/java/com/android/server/wm/ActivityTaskSupervisor.java @@ -2901,6 +2901,8 @@ public class ActivityTaskSupervisor implements RecentTasks.Callbacks { ActivityRecord fillAndReturnTop(Task task, TaskInfo info) { info.numActivities = 0; info.baseActivity = null; + info.capturedLink = null; + info.capturedLinkTimestamp = 0; mInfo = info; task.forAllActivities(this); final ActivityRecord top = mTopRunning; diff --git a/services/core/java/com/android/server/wm/BackgroundActivityStartController.java b/services/core/java/com/android/server/wm/BackgroundActivityStartController.java index 54024e92f95f..02c8a4999f4d 100644 --- a/services/core/java/com/android/server/wm/BackgroundActivityStartController.java +++ b/services/core/java/com/android/server/wm/BackgroundActivityStartController.java @@ -20,9 +20,11 @@ import static android.Manifest.permission.START_ACTIVITIES_FROM_BACKGROUND; import static android.app.ActivityManager.PROCESS_STATE_NONEXISTENT; import static android.app.ActivityOptions.BackgroundActivityStartMode; import static android.app.ActivityOptions.MODE_BACKGROUND_ACTIVITY_START_ALLOWED; +import static android.app.ActivityOptions.MODE_BACKGROUND_ACTIVITY_START_ALLOW_ALWAYS; import static android.app.ActivityOptions.MODE_BACKGROUND_ACTIVITY_START_COMPAT; import static android.app.ActivityOptions.MODE_BACKGROUND_ACTIVITY_START_DENIED; import static android.app.ActivityOptions.MODE_BACKGROUND_ACTIVITY_START_SYSTEM_DEFINED; +import static android.app.ActivityOptions.MODE_BACKGROUND_ACTIVITY_START_ALLOW_IF_VISIBLE; import static android.content.Intent.FLAG_ACTIVITY_NEW_TASK; import static android.content.pm.PackageManager.PERMISSION_GRANTED; import static android.os.Build.VERSION_CODES.UPSIDE_DOWN_CAKE; @@ -226,6 +228,21 @@ public class BackgroundActivityStartController { }; } + static String balStartModeToString(@BackgroundActivityStartMode int startMode) { + return switch (startMode) { + case MODE_BACKGROUND_ACTIVITY_START_ALLOWED -> "MODE_BACKGROUND_ACTIVITY_START_ALLOWED"; + case MODE_BACKGROUND_ACTIVITY_START_SYSTEM_DEFINED -> + "MODE_BACKGROUND_ACTIVITY_START_SYSTEM_DEFINED"; + case MODE_BACKGROUND_ACTIVITY_START_COMPAT -> "MODE_BACKGROUND_ACTIVITY_START_COMPAT"; + case MODE_BACKGROUND_ACTIVITY_START_DENIED -> "MODE_BACKGROUND_ACTIVITY_START_DENIED"; + case MODE_BACKGROUND_ACTIVITY_START_ALLOW_ALWAYS -> + "MODE_BACKGROUND_ACTIVITY_START_ALWAYS"; + case MODE_BACKGROUND_ACTIVITY_START_ALLOW_IF_VISIBLE -> + "MODE_BACKGROUND_ACTIVITY_START_ALLOW_IF_VISIBLE"; + default -> "MODE_BACKGROUND_ACTIVITY_START_ALLOWED(" + startMode + ")"; + }; + } + @GuardedBy("mService.mGlobalLock") private final HashMap<Integer, FinishedActivityEntry> mTaskIdToFinishedActivity = new HashMap<>(); @@ -464,10 +481,6 @@ public class BackgroundActivityStartController { this.mResultForRealCaller = resultForRealCaller; } - public boolean isPendingIntentBalAllowedByPermission() { - return PendingIntentRecord.isPendingIntentBalAllowedByPermission(mCheckedOptions); - } - public boolean callerExplicitOptInOrAutoOptIn() { if (mAutoOptInCaller) { return !callerExplicitOptOut(); @@ -528,6 +541,8 @@ public class BackgroundActivityStartController { sb.append("; balAllowedByPiCreatorWithHardening: ") .append(mBalAllowedByPiCreatorWithHardening); sb.append("; resultIfPiCreatorAllowsBal: ").append(mResultForCaller); + sb.append("; callerStartMode: ").append(balStartModeToString( + mCheckedOptions.getPendingIntentBackgroundActivityStartMode())); sb.append("; hasRealCaller: ").append(hasRealCaller()); sb.append("; isCallForResult: ").append(mIsCallForResult); sb.append("; isPendingIntent: ").append(isPendingIntent()); @@ -553,6 +568,8 @@ public class BackgroundActivityStartController { } sb.append("; balAllowedByPiSender: ").append(mBalAllowedByPiSender); sb.append("; resultIfPiSenderAllowsBal: ").append(mResultForRealCaller); + sb.append("; realCallerStartMode: ").append(balStartModeToString( + mCheckedOptions.getPendingIntentCreatorBackgroundActivityStartMode())); } // features sb.append("; balImproveRealCallerVisibilityCheck: ") @@ -949,7 +966,8 @@ public class BackgroundActivityStartController { } } - if (state.isPendingIntentBalAllowedByPermission() + if (state.mCheckedOptions.getPendingIntentBackgroundActivityStartMode() + == MODE_BACKGROUND_ACTIVITY_START_ALLOW_ALWAYS && hasBalPermission(state.mRealCallingUid, state.mRealCallingPid)) { return new BalVerdict(BAL_ALLOW_PERMISSION, /*background*/ false, diff --git a/services/core/java/com/android/server/wm/DeferredDisplayUpdater.java b/services/core/java/com/android/server/wm/DeferredDisplayUpdater.java index 3b999549b302..19941741ed19 100644 --- a/services/core/java/com/android/server/wm/DeferredDisplayUpdater.java +++ b/services/core/java/com/android/server/wm/DeferredDisplayUpdater.java @@ -52,7 +52,7 @@ import java.util.Objects; * display change transition. In this case, we will queue all display updates until the current * transition's collection finishes and then apply them afterwards. */ -public class DeferredDisplayUpdater implements DisplayUpdater { +class DeferredDisplayUpdater { /** * List of fields that could be deferred before applying to DisplayContent. @@ -110,7 +110,7 @@ public class DeferredDisplayUpdater implements DisplayUpdater { continueScreenUnblocking(); }; - public DeferredDisplayUpdater(@NonNull DisplayContent displayContent) { + DeferredDisplayUpdater(@NonNull DisplayContent displayContent) { mDisplayContent = displayContent; mNonOverrideDisplayInfo.copyFrom(mDisplayContent.getDisplayInfo()); } @@ -122,8 +122,7 @@ public class DeferredDisplayUpdater implements DisplayUpdater { * * @param finishCallback is called when all pending display updates are finished */ - @Override - public void updateDisplayInfo(@NonNull Runnable finishCallback) { + void updateDisplayInfo(@NonNull Runnable finishCallback) { // Get the latest display parameters from the DisplayManager final DisplayInfo displayInfo = getCurrentDisplayInfo(); @@ -310,9 +309,11 @@ public class DeferredDisplayUpdater implements DisplayUpdater { return !Objects.equals(first.uniqueId, second.uniqueId); } - @Override - public void onDisplayContentDisplayPropertiesPostChanged(int previousRotation, int newRotation, - DisplayAreaInfo newDisplayAreaInfo) { + /** + * Called after physical display has changed and after DisplayContent applied new display + * properties. + */ + void onDisplayContentDisplayPropertiesPostChanged() { // Unblock immediately in case there is no transition. This is unlikely to happen. if (mScreenUnblocker != null && !mDisplayContent.mTransitionController.inTransition()) { mScreenUnblocker.sendToTarget(); @@ -320,13 +321,16 @@ public class DeferredDisplayUpdater implements DisplayUpdater { } } - @Override - public void onDisplaySwitching(boolean switching) { + /** + * Called with {@code true} when physical display is going to switch. And {@code false} when + * the display is turned on or the device goes to sleep. + */ + void onDisplaySwitching(boolean switching) { mShouldWaitForTransitionWhenScreenOn = switching; } - @Override - public boolean waitForTransition(@NonNull Message screenUnblocker) { + /** Returns {@code true} if the transition will control when to turn on the screen. */ + boolean waitForTransition(@NonNull Message screenUnblocker) { if (!Flags.waitForTransitionOnDisplaySwitch()) return false; if (!mShouldWaitForTransitionWhenScreenOn) { return false; diff --git a/services/core/java/com/android/server/wm/DisplayContent.java b/services/core/java/com/android/server/wm/DisplayContent.java index 403c3079e968..0d165f6703db 100644 --- a/services/core/java/com/android/server/wm/DisplayContent.java +++ b/services/core/java/com/android/server/wm/DisplayContent.java @@ -159,7 +159,6 @@ import static com.android.server.wm.utils.DisplayInfoOverrides.WM_OVERRIDE_FIELD import static com.android.server.wm.utils.DisplayInfoOverrides.copyDisplayInfoFields; import static com.android.server.wm.utils.RegionUtils.forEachRectReverse; import static com.android.server.wm.utils.RegionUtils.rectListToRegion; -import static com.android.window.flags.Flags.deferDisplayUpdates; import static com.android.window.flags.Flags.explicitRefreshRateHints; import android.annotation.IntDef; @@ -478,7 +477,7 @@ class DisplayContent extends RootDisplayArea implements WindowManagerPolicy.Disp AppCompatCameraPolicy mAppCompatCameraPolicy; DisplayFrames mDisplayFrames; - final DisplayUpdater mDisplayUpdater; + final DeferredDisplayUpdater mDisplayUpdater; private boolean mInTouchMode; @@ -623,7 +622,6 @@ class DisplayContent extends RootDisplayArea implements WindowManagerPolicy.Disp @VisibleForTesting final DeviceStateController mDeviceStateController; final Consumer<DeviceStateController.DeviceState> mDeviceStateConsumer; - final PhysicalDisplaySwitchTransitionLauncher mDisplaySwitchTransitionLauncher; final RemoteDisplayChangeController mRemoteDisplayChangeController; /** Windows added since {@link #mCurrentFocus} was set to null. Used for ANR blaming. */ @@ -1140,11 +1138,7 @@ class DisplayContent extends RootDisplayArea implements WindowManagerPolicy.Disp mWallpaperController.resetLargestDisplay(display); display.getDisplayInfo(mDisplayInfo); display.getMetrics(mDisplayMetrics); - if (deferDisplayUpdates()) { - mDisplayUpdater = new DeferredDisplayUpdater(this); - } else { - mDisplayUpdater = new ImmediateDisplayUpdater(this); - } + mDisplayUpdater = new DeferredDisplayUpdater(this); mSystemGestureExclusionLimit = mWmService.mConstants.mSystemGestureExclusionLimitDp * mDisplayMetrics.densityDpi / DENSITY_DEFAULT; isDefaultDisplay = mDisplayId == DEFAULT_DISPLAY; @@ -1168,8 +1162,6 @@ class DisplayContent extends RootDisplayArea implements WindowManagerPolicy.Disp mAppTransitionController = new AppTransitionController(mWmService, this); mTransitionController.registerLegacyListener(mFixedRotationTransitionListener); mUnknownAppVisibilityController = new UnknownAppVisibilityController(mWmService, this); - mDisplaySwitchTransitionLauncher = new PhysicalDisplaySwitchTransitionLauncher(this, - mTransitionController); mRemoteDisplayChangeController = new RemoteDisplayChangeController(this); final InputChannel inputChannel = mWmService.mInputManager.monitorInput( @@ -1190,7 +1182,6 @@ class DisplayContent extends RootDisplayArea implements WindowManagerPolicy.Disp mDeviceStateConsumer = (@NonNull DeviceStateController.DeviceState newFoldState) -> { - mDisplaySwitchTransitionLauncher.foldStateChanged(newFoldState); mDisplayRotation.foldStateChanged(newFoldState); }; mDeviceStateController.registerDeviceStateCallback(mDeviceStateConsumer, @@ -3094,8 +3085,6 @@ class DisplayContent extends RootDisplayArea implements WindowManagerPolicy.Disp // metrics are updated as rotation settings might depend on them mWmService.mDisplayWindowSettings.applySettingsToDisplayLocked(this, /* includeRotationSettings */ false); - mDisplayUpdater.onDisplayContentDisplayPropertiesPreChanged(mDisplayId, - mInitialDisplayWidth, mInitialDisplayHeight, newWidth, newHeight); mDisplayRotation.physicalDisplayChanged(); mDisplayPolicy.physicalDisplayChanged(); } @@ -3130,8 +3119,7 @@ class DisplayContent extends RootDisplayArea implements WindowManagerPolicy.Disp if (physicalDisplayChanged) { mDisplayPolicy.physicalDisplayUpdated(); - mDisplayUpdater.onDisplayContentDisplayPropertiesPostChanged(currentRotation, - getRotation(), getDisplayAreaInfo()); + mDisplayUpdater.onDisplayContentDisplayPropertiesPostChanged(); } } } @@ -6278,7 +6266,7 @@ class DisplayContent extends RootDisplayArea implements WindowManagerPolicy.Disp // by looping the children, so that we don't miss any root tasks after the children size // changed or reordered. final ArrayList<Task> rootTasks = new ArrayList<>(); - forAllRootTasks(rootTask -> { + getDefaultTaskDisplayArea().forAllRootTasks(rootTask -> { for (int activityType : activityTypes) { // Collect the root tasks that are currently being organized. if (rootTask.mCreatedByOrganizer) { diff --git a/services/core/java/com/android/server/wm/DisplayUpdater.java b/services/core/java/com/android/server/wm/DisplayUpdater.java deleted file mode 100644 index 918b180ab1cb..000000000000 --- a/services/core/java/com/android/server/wm/DisplayUpdater.java +++ /dev/null @@ -1,65 +0,0 @@ -/* - * Copyright (C) 2023 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package com.android.server.wm; - -import android.annotation.NonNull; -import android.os.Message; -import android.view.Surface; -import android.window.DisplayAreaInfo; - -/** - * Interface for a helper class that manages updates of DisplayInfo coming from DisplayManager - */ -interface DisplayUpdater { - /** - * Reads the latest display parameters from the display manager and returns them in a callback. - * If there are pending display updates, it will wait for them to finish first and only then it - * will call the callback with the latest display parameters. - * - * @param callback is called when all pending display updates are finished - */ - void updateDisplayInfo(@NonNull Runnable callback); - - /** - * Called when physical display has changed and before DisplayContent has applied new display - * properties - */ - default void onDisplayContentDisplayPropertiesPreChanged(int displayId, int initialDisplayWidth, - int initialDisplayHeight, int newWidth, int newHeight) { - } - - /** - * Called after physical display has changed and after DisplayContent applied new display - * properties - */ - default void onDisplayContentDisplayPropertiesPostChanged( - @Surface.Rotation int previousRotation, @Surface.Rotation int newRotation, - @NonNull DisplayAreaInfo newDisplayAreaInfo) { - } - - /** - * Called with {@code true} when physical display is going to switch. And {@code false} when - * the display is turned on or the device goes to sleep. - */ - default void onDisplaySwitching(boolean switching) { - } - - /** Returns {@code true} if the transition will control when to turn on the screen. */ - default boolean waitForTransition(@NonNull Message screenUnBlocker) { - return false; - } -} diff --git a/services/core/java/com/android/server/wm/DisplayWindowPolicyControllerHelper.java b/services/core/java/com/android/server/wm/DisplayWindowPolicyControllerHelper.java index e0d69b063573..4ec318bee726 100644 --- a/services/core/java/com/android/server/wm/DisplayWindowPolicyControllerHelper.java +++ b/services/core/java/com/android/server/wm/DisplayWindowPolicyControllerHelper.java @@ -16,9 +16,12 @@ package com.android.server.wm; +import static android.content.pm.ActivityInfo.FLAG_CAN_DISPLAY_ON_REMOTE_DEVICES; + import android.annotation.NonNull; import android.annotation.Nullable; import android.app.WindowConfiguration; +import android.companion.virtualdevice.flags.Flags; import android.content.ComponentName; import android.content.Intent; import android.content.pm.ActivityInfo; @@ -26,6 +29,7 @@ import android.os.Process; import android.os.UserHandle; import android.util.ArraySet; import android.util.Slog; +import android.view.Display; import android.window.DisplayWindowPolicyController; import java.io.PrintWriter; @@ -80,6 +84,9 @@ class DisplayWindowPolicyControllerHelper { if (hasDisplayCategory(activities.get(i))) { return false; } + if (!launchAllowedByDisplayPolicy(activities.get(i))) { + return false; + } } return true; } @@ -95,7 +102,13 @@ class DisplayWindowPolicyControllerHelper { if (mDisplayWindowPolicyController == null) { // Missing controller means that this display has no categories for activity launch // restriction. - return !hasDisplayCategory(activityInfo); + if (hasDisplayCategory(activityInfo)) { + return false; + } + if (!launchAllowedByDisplayPolicy(activityInfo)) { + return false; + } + return true; } return mDisplayWindowPolicyController.canActivityBeLaunched(activityInfo, intent, windowingMode, launchingFromDisplayId, isNewTask); @@ -112,6 +125,24 @@ class DisplayWindowPolicyControllerHelper { return false; } + private boolean launchAllowedByDisplayPolicy(ActivityInfo aInfo) { + if (!Flags.enforceRemoteDeviceOptOutOnAllVirtualDisplays()) { + return true; + } + int displayType = mDisplayContent.getDisplay().getType(); + if (displayType != Display.TYPE_VIRTUAL && displayType != Display.TYPE_WIFI) { + return true; + } + if ((aInfo.flags & FLAG_CAN_DISPLAY_ON_REMOTE_DEVICES) == 0) { + Slog.d(TAG, + String.format("Checking activity launch on display %d, activity requires" + + " android:canDisplayOnRemoteDevices=true", + mDisplayContent.mDisplayId)); + return false; + } + return true; + } + /** * @see DisplayWindowPolicyController#keepActivityOnWindowFlagsChanged(ActivityInfo, int, int) */ diff --git a/services/core/java/com/android/server/wm/DisplayWindowSettingsProvider.java b/services/core/java/com/android/server/wm/DisplayWindowSettingsProvider.java index 8bd8098b6be9..27e6e0997c89 100644 --- a/services/core/java/com/android/server/wm/DisplayWindowSettingsProvider.java +++ b/services/core/java/com/android/server/wm/DisplayWindowSettingsProvider.java @@ -55,8 +55,10 @@ import java.io.FileOutputStream; import java.io.IOException; import java.io.InputStream; import java.io.OutputStream; +import java.util.List; import java.util.Map; import java.util.Set; +import java.util.function.Consumer; /** * Implementation of {@link SettingsProvider} that reads the base settings provided in a display @@ -152,19 +154,35 @@ class DisplayWindowSettingsProvider implements SettingsProvider { /** * Removes display override settings that are no longer associated with active displays. - * This is necessary because displays can be dynamically added or removed during - * the system's lifecycle (e.g., user switch, system server restart). + * <p> + * This cleanup process is essential due to the dynamic nature of displays, which can + * be added or removed during various system events such as user switching or + * system server restarts. * - * @param root The root window container used to obtain the currently active displays. + * @param wms the WindowManagerService instance for retrieving all possible {@link DisplayInfo} + * for the given logical display. + * @param root the root window container used to obtain the currently active displays. */ - void removeStaleDisplaySettings(@NonNull RootWindowContainer root) { + void removeStaleDisplaySettingsLocked(@NonNull WindowManagerService wms, + @NonNull RootWindowContainer root) { if (!Flags.perUserDisplayWindowSettings()) { return; } final Set<String> displayIdentifiers = new ArraySet<>(); + final Consumer<DisplayInfo> addDisplayIdentifier = + displayInfo -> displayIdentifiers.add(mOverrideSettings.getIdentifier(displayInfo)); root.forAllDisplays(dc -> { - final String identifier = mOverrideSettings.getIdentifier(dc.getDisplayInfo()); - displayIdentifiers.add(identifier); + // Begin with the current display's information. Note that the display layout of the + // current device state might not include this display (e.g., external or virtual + // displays), resulting in empty possible display info. + addDisplayIdentifier.accept(dc.getDisplayInfo()); + + // Then, add all possible display information for this display if available. + final List<DisplayInfo> displayInfos = wms.getPossibleDisplayInfoLocked(dc.mDisplayId); + final int size = displayInfos.size(); + for (int i = 0; i < size; i++) { + addDisplayIdentifier.accept(displayInfos.get(i)); + } }); mOverrideSettings.removeStaleDisplaySettings(displayIdentifiers); } diff --git a/services/core/java/com/android/server/wm/DragDropController.java b/services/core/java/com/android/server/wm/DragDropController.java index 6abef8b9a048..c849a37ede53 100644 --- a/services/core/java/com/android/server/wm/DragDropController.java +++ b/services/core/java/com/android/server/wm/DragDropController.java @@ -16,7 +16,6 @@ package com.android.server.wm; -import static android.content.ClipDescription.EXTRA_HIDE_DRAG_SOURCE_TASK_ID; import static android.os.Trace.TRACE_TAG_WINDOW_MANAGER; import static android.view.View.DRAG_FLAG_GLOBAL; import static android.view.View.DRAG_FLAG_GLOBAL_SAME_APPLICATION; @@ -228,7 +227,7 @@ class DragDropController { final Display display = displayContent.getDisplay(); touchFocusTransferredFuture = mCallback.get().registerInputChannel( mDragState, display, mService.mInputManager, - callingWin.mInputChannel); + callingWin.mInputChannelToken); } else { // Skip surface logic for a drag triggered by an AccessibilityAction mDragState.broadcastDragStartedLocked(touchX, touchY); diff --git a/services/core/java/com/android/server/wm/DragState.java b/services/core/java/com/android/server/wm/DragState.java index ba74f5076bc0..59435b86c375 100644 --- a/services/core/java/com/android/server/wm/DragState.java +++ b/services/core/java/com/android/server/wm/DragState.java @@ -456,10 +456,6 @@ class DragState { } } - InputChannel getInputChannel() { - return mInputInterceptor == null ? null : mInputInterceptor.mClientChannel; - } - InputWindowHandle getInputWindowHandle() { return mInputInterceptor == null ? null : mInputInterceptor.mDragWindowHandle; } diff --git a/services/core/java/com/android/server/wm/ImmediateDisplayUpdater.java b/services/core/java/com/android/server/wm/ImmediateDisplayUpdater.java deleted file mode 100644 index 4af9013d7f4a..000000000000 --- a/services/core/java/com/android/server/wm/ImmediateDisplayUpdater.java +++ /dev/null @@ -1,58 +0,0 @@ -/* - * Copyright (C) 2023 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package com.android.server.wm; - -import android.annotation.NonNull; -import android.view.DisplayInfo; -import android.window.DisplayAreaInfo; - -/** - * DisplayUpdater that immediately applies new DisplayInfo properties - */ -public class ImmediateDisplayUpdater implements DisplayUpdater { - - private final DisplayContent mDisplayContent; - private final DisplayInfo mDisplayInfo = new DisplayInfo(); - - public ImmediateDisplayUpdater(@NonNull DisplayContent displayContent) { - mDisplayContent = displayContent; - mDisplayInfo.copyFrom(mDisplayContent.getDisplayInfo()); - } - - @Override - public void updateDisplayInfo(Runnable callback) { - mDisplayContent.mWmService.mDisplayManagerInternal.getNonOverrideDisplayInfo( - mDisplayContent.mDisplayId, mDisplayInfo); - mDisplayContent.onDisplayInfoUpdated(mDisplayInfo); - callback.run(); - } - - @Override - public void onDisplayContentDisplayPropertiesPreChanged(int displayId, int initialDisplayWidth, - int initialDisplayHeight, int newWidth, int newHeight) { - mDisplayContent.mDisplaySwitchTransitionLauncher.requestDisplaySwitchTransitionIfNeeded( - displayId, initialDisplayWidth, initialDisplayHeight, newWidth, newHeight); - } - - @Override - public void onDisplayContentDisplayPropertiesPostChanged(int previousRotation, int newRotation, - DisplayAreaInfo newDisplayAreaInfo) { - mDisplayContent.mDisplaySwitchTransitionLauncher.onDisplayUpdated(previousRotation, - newRotation, - newDisplayAreaInfo); - } -} diff --git a/services/core/java/com/android/server/wm/InputMonitor.java b/services/core/java/com/android/server/wm/InputMonitor.java index b496a65ba4a6..b8869f159169 100644 --- a/services/core/java/com/android/server/wm/InputMonitor.java +++ b/services/core/java/com/android/server/wm/InputMonitor.java @@ -439,8 +439,7 @@ final class InputMonitor { final InputMethodManagerInternal inputMethodManagerInternal = LocalServices.getService(InputMethodManagerInternal.class); if (inputMethodManagerInternal != null) { - // TODO(b/308479256): Check if hiding "all" IMEs is OK or not. - inputMethodManagerInternal.hideAllInputMethods( + inputMethodManagerInternal.hideInputMethod( SoftInputShowHideReason.HIDE_RECENTS_ANIMATION, mDisplayContent.getDisplayId()); } diff --git a/services/core/java/com/android/server/wm/KeyguardController.java b/services/core/java/com/android/server/wm/KeyguardController.java index 872b4e102565..7a0fd3e34fdd 100644 --- a/services/core/java/com/android/server/wm/KeyguardController.java +++ b/services/core/java/com/android/server/wm/KeyguardController.java @@ -60,7 +60,6 @@ import android.view.WindowManager; import com.android.internal.policy.IKeyguardDismissCallback; import com.android.server.inputmethod.InputMethodManagerInternal; import com.android.server.policy.WindowManagerPolicy; -import com.android.window.flags.Flags; import java.io.PrintWriter; @@ -198,14 +197,6 @@ class KeyguardController { setWakeTransitionReady(); return; } - EventLogTags.writeWmSetKeyguardShown( - displayId, - keyguardShowing ? 1 : 0, - aodShowing ? 1 : 0, - state.mKeyguardGoingAway ? 1 : 0, - state.mOccluded ? 1 : 0, - "setKeyguardShown"); - // Update the task snapshot if the screen will not be turned off. To make sure that the // unlocking animation can animate consistent content. The conditions are: // - Either AOD or keyguard changes to be showing. So if the states change individually, @@ -224,6 +215,7 @@ class KeyguardController { state.mKeyguardShowing = keyguardShowing; state.mAodShowing = aodShowing; + state.writeEventLog("setKeyguardShown"); if (keyguardChanged) { // Irrelevant to AOD. @@ -232,19 +224,13 @@ class KeyguardController { state.mDismissalRequested = false; } if (goingAwayRemoved - || (Flags.keyguardAppearTransition() && keyguardShowing - && !Display.isOffState(dc.getDisplayInfo().state))) { + || (keyguardShowing && !Display.isOffState(dc.getDisplayInfo().state))) { // Keyguard decided to show or stopped going away. Send a transition to animate back // to the locked state before holding the sleep token again - final DisplayContent transitionDc = Flags.keyguardAppearTransition() - ? dc - : mRootWindowContainer.getDefaultDisplay(); - transitionDc.requestTransitionAndLegacyPrepare( + dc.requestTransitionAndLegacyPrepare( TRANSIT_TO_FRONT, TRANSIT_FLAG_KEYGUARD_APPEARING); - if (Flags.keyguardAppearTransition()) { - dc.mWallpaperController.adjustWallpaperWindows(); - } - transitionDc.executeAppTransition(); + dc.mWallpaperController.adjustWallpaperWindows(); + dc.executeAppTransition(); } } @@ -284,13 +270,7 @@ class KeyguardController { mService.deferWindowLayout(); state.mKeyguardGoingAway = true; try { - EventLogTags.writeWmSetKeyguardShown( - displayId, - state.mKeyguardShowing ? 1 : 0, - state.mAodShowing ? 1 : 0, - 1 /* keyguardGoingAway */, - state.mOccluded ? 1 : 0, - "keyguardGoingAway"); + state.writeEventLog("keyguardGoingAway"); final int transitFlags = convertTransitFlags(flags); final DisplayContent dc = mRootWindowContainer.getDefaultDisplay(); dc.prepareAppTransition(TRANSIT_KEYGUARD_GOING_AWAY, transitFlags); @@ -436,8 +416,9 @@ class KeyguardController { } final TransitionController tc = mRootWindowContainer.mTransitionController; + final KeyguardDisplayState state = getDisplayState(displayId); - final boolean occluded = getDisplayState(displayId).mOccluded; + final boolean occluded = state.mOccluded; final boolean performTransition = isKeyguardLocked(displayId); final boolean executeTransition = performTransition && !tc.isCollecting(); @@ -481,7 +462,7 @@ class KeyguardController { /** * Called when keyguard going away state changed. */ - private void handleKeyguardGoingAwayChanged(DisplayContent dc) { + private void handleDismissInsecureKeyguard(DisplayContent dc) { mService.deferWindowLayout(); try { dc.prepareAppTransition(TRANSIT_KEYGUARD_GOING_AWAY, 0 /* transitFlags */); @@ -646,6 +627,16 @@ class KeyguardController { mSleepTokenAcquirer.release(mDisplayId); } + void writeEventLog(String reason) { + EventLogTags.writeWmSetKeyguardShown( + mDisplayId, + mKeyguardShowing ? 1 : 0, + mAodShowing ? 1 : 0, + mKeyguardGoingAway ? 1 : 0, + mOccluded ? 1 : 0, + reason); + } + /** * Updates keyguard status if the top task could be visible. The top task may occlude * keyguard, request to dismiss keyguard or make insecure keyguard go away based on its @@ -715,23 +706,16 @@ class KeyguardController { } boolean hasChange = false; - if (lastOccluded != mOccluded) { - if (mDisplayId == DEFAULT_DISPLAY) { - EventLogTags.writeWmSetKeyguardShown( - mDisplayId, - mKeyguardShowing ? 1 : 0, - mAodShowing ? 1 : 0, - mKeyguardGoingAway ? 1 : 0, - mOccluded ? 1 : 0, - "updateVisibility"); - } - controller.handleOccludedChanged(mDisplayId, mTopOccludesActivity); + if (!lastKeyguardGoingAway && mKeyguardGoingAway) { + writeEventLog("dismissIfInsecure"); + controller.handleDismissInsecureKeyguard(display); hasChange = true; - } else if (!lastKeyguardGoingAway && mKeyguardGoingAway) { - controller.handleKeyguardGoingAwayChanged(display); + } else if (lastOccluded != mOccluded) { + controller.handleOccludedChanged(mDisplayId, mTopOccludesActivity); hasChange = true; } - // Collect the participates for shell transition, so that transition won't happen too + + // Collect the participants for shell transition, so that transition won't happen too // early since the transition was set ready. if (hasChange && top != null && (mOccluded || mKeyguardGoingAway)) { display.mTransitionController.collect(top); diff --git a/services/core/java/com/android/server/wm/LetterboxUiController.java b/services/core/java/com/android/server/wm/LetterboxUiController.java index 444097a3ea05..291eab1b2d94 100644 --- a/services/core/java/com/android/server/wm/LetterboxUiController.java +++ b/services/core/java/com/android/server/wm/LetterboxUiController.java @@ -325,11 +325,6 @@ final class LetterboxUiController { : mAppCompatConfiguration.getLetterboxVerticalPositionMultiplier(tabletopMode); } - float getFixedOrientationLetterboxAspectRatio(@NonNull Configuration parentConfiguration) { - return mActivityRecord.mAppCompatController.getAppCompatAspectRatioOverrides() - .getFixedOrientationLetterboxAspectRatio(parentConfiguration); - } - boolean isLetterboxEducationEnabled() { return mAppCompatConfiguration.getIsEducationEnabled(); } diff --git a/services/core/java/com/android/server/wm/PhysicalDisplaySwitchTransitionLauncher.java b/services/core/java/com/android/server/wm/PhysicalDisplaySwitchTransitionLauncher.java deleted file mode 100644 index 3cf301c1d730..000000000000 --- a/services/core/java/com/android/server/wm/PhysicalDisplaySwitchTransitionLauncher.java +++ /dev/null @@ -1,187 +0,0 @@ -/* - * Copyright (C) 2022 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package com.android.server.wm; - -import static android.view.WindowManager.TRANSIT_CHANGE; -import static android.view.WindowManager.TRANSIT_FLAG_PHYSICAL_DISPLAY_SWITCH; - -import static com.android.internal.R.bool.config_unfoldTransitionEnabled; -import static com.android.server.wm.ActivityTaskManagerService.POWER_MODE_REASON_CHANGE_DISPLAY; -import static com.android.server.wm.DeviceStateController.DeviceState.FOLDED; -import static com.android.server.wm.DeviceStateController.DeviceState.HALF_FOLDED; -import static com.android.server.wm.DeviceStateController.DeviceState.OPEN; - -import android.animation.ValueAnimator; -import android.annotation.NonNull; -import android.annotation.Nullable; -import android.content.Context; -import android.graphics.Rect; -import android.window.DisplayAreaInfo; -import android.window.TransitionRequestInfo; -import android.window.WindowContainerTransaction; - -import com.android.internal.annotations.VisibleForTesting; -import com.android.internal.protolog.ProtoLogGroup; -import com.android.internal.protolog.ProtoLog; -import com.android.server.wm.DeviceStateController.DeviceState; - -public class PhysicalDisplaySwitchTransitionLauncher { - - private final DisplayContent mDisplayContent; - private final ActivityTaskManagerService mAtmService; - private final Context mContext; - private final TransitionController mTransitionController; - - /** - * If on a foldable device represents whether we need to show unfold animation when receiving - * a physical display switch event - */ - private boolean mShouldRequestTransitionOnDisplaySwitch = false; - /** - * Current device state from {@link android.hardware.devicestate.DeviceStateManager} - */ - private DeviceState mDeviceState = DeviceState.UNKNOWN; - private Transition mTransition; - - public PhysicalDisplaySwitchTransitionLauncher(DisplayContent displayContent, - TransitionController transitionController) { - this(displayContent, displayContent.mWmService.mAtmService, - displayContent.mWmService.mContext, transitionController); - } - - @VisibleForTesting - public PhysicalDisplaySwitchTransitionLauncher(DisplayContent displayContent, - ActivityTaskManagerService service, Context context, - TransitionController transitionController) { - mDisplayContent = displayContent; - mAtmService = service; - mContext = context; - mTransitionController = transitionController; - } - - /** - * Called by the display manager just before it applied the device state, it is guaranteed - * that in case of physical display change the - * {@link PhysicalDisplaySwitchTransitionLauncher#requestDisplaySwitchTransitionIfNeeded} - * method will be invoked *after* this one. - */ - void foldStateChanged(DeviceState newDeviceState) { - boolean isUnfolding = mDeviceState == FOLDED - && (newDeviceState == HALF_FOLDED || newDeviceState == OPEN); - - if (isUnfolding) { - // Request transition only if we are unfolding the device - mShouldRequestTransitionOnDisplaySwitch = true; - } else if (newDeviceState != HALF_FOLDED && newDeviceState != OPEN) { - // Cancel the transition request in case if we are folding or switching to back - // to the rear display before the displays got switched - mShouldRequestTransitionOnDisplaySwitch = false; - } - - mDeviceState = newDeviceState; - } - - /** - * Requests to start a transition for the physical display switch - */ - public void requestDisplaySwitchTransitionIfNeeded(int displayId, int oldDisplayWidth, - int oldDisplayHeight, int newDisplayWidth, int newDisplayHeight) { - if (!mShouldRequestTransitionOnDisplaySwitch) return; - if (!mTransitionController.isShellTransitionsEnabled()) return; - if (!mDisplayContent.getLastHasContent()) return; - - boolean shouldRequestUnfoldTransition = mContext.getResources() - .getBoolean(config_unfoldTransitionEnabled) && ValueAnimator.areAnimatorsEnabled(); - - if (!shouldRequestUnfoldTransition) { - return; - } - - mTransition = null; - - if (mTransitionController.isCollecting()) { - // Add display container to the currently collecting transition - mTransition = mTransitionController.getCollectingTransition(); - mTransition.collect(mDisplayContent); - - // Make sure that transition is not ready until we finish the remote display change - mTransition.setReady(mDisplayContent, false); - mTransition.addFlag(TRANSIT_FLAG_PHYSICAL_DISPLAY_SWITCH); - - ProtoLog.d(ProtoLogGroup.WM_DEBUG_WINDOW_TRANSITIONS, - "Adding display switch to existing collecting transition"); - } else { - final TransitionRequestInfo.DisplayChange displayChange = - new TransitionRequestInfo.DisplayChange(displayId); - - final Rect startAbsBounds = new Rect(0, 0, oldDisplayWidth, oldDisplayHeight); - displayChange.setStartAbsBounds(startAbsBounds); - final Rect endAbsBounds = new Rect(0, 0, newDisplayWidth, newDisplayHeight); - displayChange.setEndAbsBounds(endAbsBounds); - displayChange.setPhysicalDisplayChanged(true); - - mTransition = mTransitionController.requestStartDisplayTransition(TRANSIT_CHANGE, - 0 /* flags */, mDisplayContent, null /* remoteTransition */, displayChange); - mTransition.collect(mDisplayContent); - } - - if (mTransition != null) { - mAtmService.startPowerMode(POWER_MODE_REASON_CHANGE_DISPLAY); - } - - mShouldRequestTransitionOnDisplaySwitch = false; - } - - /** - * Called when physical display is getting updated, this could happen e.g. on foldable - * devices when the physical underlying display is replaced. - * - * @param fromRotation rotation before the display change - * @param toRotation rotation after the display change - * @param newDisplayAreaInfo display area info after the display change - */ - public void onDisplayUpdated(int fromRotation, int toRotation, - @NonNull DisplayAreaInfo newDisplayAreaInfo) { - if (mTransition == null) return; - - final boolean started = mDisplayContent.mRemoteDisplayChangeController - .performRemoteDisplayChange(fromRotation, toRotation, newDisplayAreaInfo, - this::continueDisplayUpdate); - - if (!started) { - markTransitionAsReady(); - } - } - - private void continueDisplayUpdate(@Nullable WindowContainerTransaction transaction) { - if (mTransition == null) return; - - if (transaction != null) { - mAtmService.mWindowOrganizerController.applyTransaction(transaction); - } - - markTransitionAsReady(); - } - - private void markTransitionAsReady() { - if (mTransition == null) return; - - mTransition.setAllReady(); - mTransition = null; - } - -} diff --git a/services/core/java/com/android/server/wm/PossibleDisplayInfoMapper.java b/services/core/java/com/android/server/wm/PossibleDisplayInfoMapper.java index e3a2065838d1..6e8797791c97 100644 --- a/services/core/java/com/android/server/wm/PossibleDisplayInfoMapper.java +++ b/services/core/java/com/android/server/wm/PossibleDisplayInfoMapper.java @@ -57,7 +57,7 @@ public class PossibleDisplayInfoMapper { * Returns, for the given displayId, a list of unique display infos. List contains each * supported device state. * <p>List contents are guaranteed to be unique, but returned as a list rather than a set to - * minimize copies needed to make an iteraable data structure. + * minimize copies needed to make an iterable data structure. */ public List<DisplayInfo> getPossibleDisplayInfos(int displayId) { // Update display infos before returning, since any cached values would have been removed diff --git a/services/core/java/com/android/server/wm/SnapshotController.java b/services/core/java/com/android/server/wm/SnapshotController.java index cb388efdae89..99e1e8b1a5c6 100644 --- a/services/core/java/com/android/server/wm/SnapshotController.java +++ b/services/core/java/com/android/server/wm/SnapshotController.java @@ -186,11 +186,11 @@ class SnapshotController { } mActivitySnapshotController.handleTransitionFinish(windows); mActivitySnapshotController.endSnapshotProcess(); - // Remove task snapshot if it is visible at the end of transition. + // Remove task snapshot if it is visible at the end of transition, except for PiP. for (int i = changeInfos.size() - 1; i >= 0; --i) { final WindowContainer wc = changeInfos.get(i).mContainer; final Task task = wc.asTask(); - if (task != null && wc.isVisibleRequested()) { + if (task != null && wc.isVisibleRequested() && !task.inPinnedWindowingMode()) { final TaskSnapshot snapshot = mTaskSnapshotController.getSnapshot(task.mTaskId, task.mUserId, false /* restoreFromDisk */, false /* isLowResolution */); if (snapshot != null) { diff --git a/services/core/java/com/android/server/wm/Task.java b/services/core/java/com/android/server/wm/Task.java index ab1e96952c53..5cef3a1bfc1d 100644 --- a/services/core/java/com/android/server/wm/Task.java +++ b/services/core/java/com/android/server/wm/Task.java @@ -2287,7 +2287,7 @@ class Task extends TaskFragment { // Apply crop to root tasks only and clear the crops of the descendant tasks. int width = 0; int height = 0; - if (isRootTask()) { + if (isRootTask() && !mTransitionController.mIsWaitingForDisplayEnabled) { final Rect taskBounds = getBounds(); width = taskBounds.width(); height = taskBounds.height(); @@ -3398,10 +3398,6 @@ class Task extends TaskFragment { && top.isEligibleForLetterboxEducation(); appCompatTaskInfo.isLetterboxEducationEnabled = top != null && top.mLetterboxUiController.isLetterboxEducationEnabled(); - // Whether the direct top activity requested showing camera compat control. - appCompatTaskInfo.cameraCompatTaskInfo.cameraCompatControlState = isTopActivityResumed - ? top.getCameraCompatControlState() - : CameraCompatTaskInfo.CAMERA_COMPAT_CONTROL_HIDDEN; final Task parentTask = getParent() != null ? getParent().asTask() : null; info.parentTaskId = parentTask != null && parentTask.mCreatedByOrganizer @@ -3413,6 +3409,7 @@ class Task extends TaskFragment { info.isSleeping = shouldSleepActivities(); info.isTopActivityTransparent = top != null && !top.fillsParent(); info.isTopActivityStyleFloating = top != null && top.isStyleFloating(); + info.lastNonFullscreenBounds = topTask.mLastNonFullscreenBounds; appCompatTaskInfo.topActivityLetterboxVerticalPosition = TaskInfo.PROPERTY_VALUE_UNSET; appCompatTaskInfo.topActivityLetterboxHorizontalPosition = TaskInfo.PROPERTY_VALUE_UNSET; appCompatTaskInfo.topActivityLetterboxWidth = TaskInfo.PROPERTY_VALUE_UNSET; @@ -3512,6 +3509,9 @@ class Task extends TaskFragment { if (task.effectiveUid != baseActivityUid) { info.baseActivity = new ComponentName("", ""); } + + info.capturedLink = null; + info.capturedLinkTimestamp = 0; } @Nullable PictureInPictureParams getPictureInPictureParams() { diff --git a/services/core/java/com/android/server/wm/TaskFragment.java b/services/core/java/com/android/server/wm/TaskFragment.java index c83b28055a2f..ed0dc3be9465 100644 --- a/services/core/java/com/android/server/wm/TaskFragment.java +++ b/services/core/java/com/android/server/wm/TaskFragment.java @@ -2819,7 +2819,21 @@ class TaskFragment extends WindowContainer<WindowContainer> { mClearedTaskForReuse, mClearedTaskFragmentForPip, mClearedForReorderActivityToFront, - calculateMinDimension()); + calculateMinDimension(), + isTopNonFinishingChild()); + } + + private boolean isTopNonFinishingChild() { + final WindowContainer<?> parent = getParent(); + if (parent == null) { + // Either the TaskFragment is not attached or is going to destroy. Return false. + return false; + } + final ActivityRecord topNonFishingActivity = parent.getActivity(ar -> !ar.finishing); + // If the parent's top non-finishing activity is this TaskFragment's, it means + // this TaskFragment is the top non-finishing container of its parent. + return topNonFishingActivity != null && topNonFishingActivity + .equals(getTopNonFinishingActivity()); } /** diff --git a/services/core/java/com/android/server/wm/TaskOrganizerController.java b/services/core/java/com/android/server/wm/TaskOrganizerController.java index 6e36d427bd13..2c5beda1d05a 100644 --- a/services/core/java/com/android/server/wm/TaskOrganizerController.java +++ b/services/core/java/com/android/server/wm/TaskOrganizerController.java @@ -17,7 +17,6 @@ package com.android.server.wm; import static android.app.ActivityTaskManager.INVALID_TASK_ID; -import static android.app.CameraCompatTaskInfo.cameraCompatControlStateToString; import static android.window.StartingWindowRemovalInfo.DEFER_MODE_NONE; import static android.window.StartingWindowRemovalInfo.DEFER_MODE_NORMAL; import static android.window.StartingWindowRemovalInfo.DEFER_MODE_ROTATION; @@ -1128,35 +1127,6 @@ class TaskOrganizerController extends ITaskOrganizerController.Stub { } } - @Override - public void updateCameraCompatControlState(WindowContainerToken token, int state) { - enforceTaskPermission("updateCameraCompatControlState()"); - final long origId = Binder.clearCallingIdentity(); - try { - synchronized (mGlobalLock) { - final WindowContainer wc = WindowContainer.fromBinder(token.asBinder()); - if (wc == null) { - Slog.w(TAG, "Could not resolve window from token"); - return; - } - final Task task = wc.asTask(); - if (task == null) { - Slog.w(TAG, "Could not resolve task from token"); - return; - } - ProtoLog.v(WM_DEBUG_WINDOW_ORGANIZER, - "Update camera compat control state to %s for taskId=%d", - cameraCompatControlStateToString(state), task.mTaskId); - final ActivityRecord activity = task.getTopNonFinishingActivity(); - if (activity != null) { - activity.updateCameraCompatStateFromUser(state); - } - } - } finally { - Binder.restoreCallingIdentity(origId); - } - } - public boolean handleInterceptBackPressedOnTaskRoot(Task task) { if (!shouldInterceptBackPressedOnRootTask(task)) { return false; diff --git a/services/core/java/com/android/server/wm/Transition.java b/services/core/java/com/android/server/wm/Transition.java index 358adc3352e7..0b79f14051dc 100644 --- a/services/core/java/com/android/server/wm/Transition.java +++ b/services/core/java/com/android/server/wm/Transition.java @@ -18,6 +18,7 @@ package com.android.server.wm; import static android.app.ActivityOptions.ANIM_CUSTOM; import static android.app.ActivityOptions.ANIM_OPEN_CROSS_PROFILE_APPS; +import static android.app.ActivityOptions.ANIM_SCENE_TRANSITION; import static android.app.WindowConfiguration.ACTIVITY_TYPE_HOME; import static android.app.WindowConfiguration.ACTIVITY_TYPE_RECENTS; import static android.app.WindowConfiguration.ACTIVITY_TYPE_STANDARD; @@ -1936,8 +1937,7 @@ class Transition implements BLASTSyncEngine.TransactionReadyListener { for (int i = changes.size() - 1; i >= 0; --i) { final WindowContainer<?> container = mTargets.get(i).mContainer; if (container.asActivityRecord() != null - || (container.asTask() != null - && mOverrideOptions.getOverrideTaskTransition())) { + || shouldApplyAnimOptionsToTask(container.asTask())) { changes.get(i).setAnimationOptions(mOverrideOptions); // TODO(b/295805497): Extract mBackgroundColor from AnimationOptions. changes.get(i).setBackgroundColor(mOverrideOptions.getBackgroundColor()); @@ -1951,6 +1951,16 @@ class Transition implements BLASTSyncEngine.TransactionReadyListener { updateActivityTargetForCrossProfileAnimation(info); } + private boolean shouldApplyAnimOptionsToTask(@Nullable Task task) { + if (task == null || mOverrideOptions == null) { + return false; + } + final int animType = mOverrideOptions.getType(); + // Only apply AnimationOptions to Task if it is specified in #getOverrideTaskTransition + // or it's ANIM_SCENE_TRANSITION. + return animType == ANIM_SCENE_TRANSITION || mOverrideOptions.getOverrideTaskTransition(); + } + private boolean shouldApplyAnimOptionsToEmbeddedTf(@Nullable TaskFragment taskFragment) { if (taskFragment == null || !taskFragment.isEmbedded()) { return false; @@ -2185,8 +2195,7 @@ class Transition implements BLASTSyncEngine.TransactionReadyListener { for (int i = mParticipants.size() - 1; i >= 0; --i) { final WallpaperWindowToken wallpaper = mParticipants.valueAt(i).asWallpaperToken(); if (wallpaper != null) { - if (!wallpaper.isVisible() && (wallpaper.isVisibleRequested() - || (Flags.ensureWallpaperInTransitions() && showWallpaper))) { + if (!wallpaper.isVisible() && wallpaper.isVisibleRequested()) { wallpaper.commitVisibility(showWallpaper); } else if (Flags.ensureWallpaperInTransitions() && wallpaper.isVisible() && !showWallpaper && !wallpaper.getDisplayContent().isKeyguardLocked() @@ -2378,6 +2387,7 @@ class Transition implements BLASTSyncEngine.TransactionReadyListener { sb.append(" id=" + mSyncId); sb.append(" type=" + transitTypeToString(mType)); sb.append(" flags=0x" + Integer.toHexString(mFlags)); + sb.append(" overrideAnimOptions=" + mOverrideOptions); sb.append('}'); return sb.toString(); } diff --git a/services/core/java/com/android/server/wm/WindowAnimationSpec.java b/services/core/java/com/android/server/wm/WindowAnimationSpec.java index 34b9913c9738..2c58c61701cc 100644 --- a/services/core/java/com/android/server/wm/WindowAnimationSpec.java +++ b/services/core/java/com/android/server/wm/WindowAnimationSpec.java @@ -97,10 +97,10 @@ public class WindowAnimationSpec implements AnimationSpec { /** * @return If a window animation has outsets applied to it. - * @see Animation#hasExtension() + * @see Animation#getExtensionEdges() */ public boolean hasExtension() { - return mAnimation.hasExtension(); + return mAnimation.getExtensionEdges() != 0; } @Override diff --git a/services/core/java/com/android/server/wm/WindowManagerInternal.java b/services/core/java/com/android/server/wm/WindowManagerInternal.java index 88e8064edc0e..48a5050c08b0 100644 --- a/services/core/java/com/android/server/wm/WindowManagerInternal.java +++ b/services/core/java/com/android/server/wm/WindowManagerInternal.java @@ -41,7 +41,6 @@ import android.view.Display; import android.view.IInputFilter; import android.view.IRemoteAnimationFinishedCallback; import android.view.IWindow; -import android.view.InputChannel; import android.view.MagnificationSpec; import android.view.RemoteAnimationTarget; import android.view.Surface; @@ -377,10 +376,10 @@ public abstract class WindowManagerInternal { public interface IDragDropCallback { default CompletableFuture<Boolean> registerInputChannel( DragState state, Display display, InputManagerService service, - InputChannel source) { + IBinder sourceInputChannelToken) { return state.register(display) .thenApply(unused -> - service.startDragAndDrop(source.getToken(), state.getInputChannel())); + service.startDragAndDrop(sourceInputChannelToken, state.getInputToken())); } /** diff --git a/services/core/java/com/android/server/wm/WindowManagerService.java b/services/core/java/com/android/server/wm/WindowManagerService.java index a21806819d80..13453a63a1ab 100644 --- a/services/core/java/com/android/server/wm/WindowManagerService.java +++ b/services/core/java/com/android/server/wm/WindowManagerService.java @@ -118,12 +118,12 @@ import static com.android.server.LockGuard.installLock; import static com.android.server.policy.PhoneWindowManager.TRACE_WAIT_FOR_ALL_WINDOWS_DRAWN_METHOD; import static com.android.server.policy.WindowManagerPolicy.FINISH_LAYOUT_REDO_WALLPAPER; import static com.android.server.wm.ActivityTaskManagerService.POWER_MODE_REASON_CHANGE_DISPLAY; -import static com.android.server.wm.DisplayContent.IME_TARGET_CONTROL; -import static com.android.server.wm.DisplayContent.IME_TARGET_LAYERING; import static com.android.server.wm.AppCompatConfiguration.LETTERBOX_BACKGROUND_APP_COLOR_BACKGROUND; import static com.android.server.wm.AppCompatConfiguration.LETTERBOX_BACKGROUND_APP_COLOR_BACKGROUND_FLOATING; import static com.android.server.wm.AppCompatConfiguration.LETTERBOX_BACKGROUND_SOLID_COLOR; import static com.android.server.wm.AppCompatConfiguration.LETTERBOX_BACKGROUND_WALLPAPER; +import static com.android.server.wm.DisplayContent.IME_TARGET_CONTROL; +import static com.android.server.wm.DisplayContent.IME_TARGET_LAYERING; import static com.android.server.wm.RootWindowContainer.MATCH_ATTACHED_TASK_OR_RECENT_TASKS; import static com.android.server.wm.SensitiveContentPackages.PackageInfo; import static com.android.server.wm.SurfaceAnimator.ANIMATION_TYPE_ALL; @@ -357,7 +357,6 @@ import com.android.server.policy.WindowManagerPolicy.ScreenOffListener; import com.android.server.power.ShutdownThread; import com.android.server.utils.PriorityDump; import com.android.server.wallpaper.WallpaperCropper.WallpaperCropUtils; -import com.android.window.flags.Flags; import dalvik.annotation.optimization.NeverCompile; @@ -3750,7 +3749,7 @@ public class WindowManagerService extends IWindowManager.Stub } mCurrentUserId = newUserId; mDisplayWindowSettingsProvider.setOverrideSettingsForUser(newUserId); - mDisplayWindowSettingsProvider.removeStaleDisplaySettings(mRoot); + mDisplayWindowSettingsProvider.removeStaleDisplaySettingsLocked(this, mRoot); mPolicy.setCurrentUserLw(newUserId); mKeyguardDisableHandler.setCurrentUser(newUserId); @@ -5491,7 +5490,7 @@ public class WindowManagerService extends IWindowManager.Stub mRoot.forAllDisplays(DisplayContent::reconfigureDisplayLocked); // Per-user display settings may leave outdated settings after user switches, especially // during reboots starting with the default user without setCurrentUser called. - mDisplayWindowSettingsProvider.removeStaleDisplaySettings(mRoot); + mDisplayWindowSettingsProvider.removeStaleDisplaySettingsLocked(this, mRoot); } } @@ -9390,11 +9389,6 @@ public class WindowManagerService extends IWindowManager.Stub return focusedActivity; } - if (!Flags.embeddedActivityBackNavFlag()) { - // Return if flag is not enabled. - return focusedActivity; - } - if (!focusedActivity.isEmbedded()) { // Return if the focused activity is not embedded. return focusedActivity; @@ -9778,7 +9772,7 @@ public class WindowManagerService extends IWindowManager.Stub Slog.e(TAG, "Host window not found"); return; } - if (hostWindow.mInputChannel == null) { + if (hostWindow.mInputChannelToken == null) { Slog.e(TAG, "Host window does not have an input channel"); return; } diff --git a/services/core/java/com/android/server/wm/WindowOrganizerController.java b/services/core/java/com/android/server/wm/WindowOrganizerController.java index bc32b91f2c57..0093e9d0788b 100644 --- a/services/core/java/com/android/server/wm/WindowOrganizerController.java +++ b/services/core/java/com/android/server/wm/WindowOrganizerController.java @@ -390,7 +390,10 @@ class WindowOrganizerController extends IWindowOrganizerController.Stub private static boolean hasActivityLaunch(@NonNull WindowContainerTransaction wct) { for (int i = 0; i < wct.getHierarchyOps().size(); ++i) { - if (wct.getHierarchyOps().get(i).getType() == HIERARCHY_OP_TYPE_LAUNCH_TASK) { + final WindowContainerTransaction.HierarchyOp op = wct.getHierarchyOps().get(i); + if (op.getType() == HIERARCHY_OP_TYPE_LAUNCH_TASK + || (op.getType() == HIERARCHY_OP_TYPE_PENDING_INTENT + && op.getPendingIntent().isActivity())) { return true; } } diff --git a/services/core/java/com/android/server/wm/WindowState.java b/services/core/java/com/android/server/wm/WindowState.java index 1cc5a8bec0c9..153d41be4fee 100644 --- a/services/core/java/com/android/server/wm/WindowState.java +++ b/services/core/java/com/android/server/wm/WindowState.java @@ -638,7 +638,7 @@ class WindowState extends WindowContainer<WindowState> implements WindowManagerP /** * Only populated if flag REMOVE_INPUT_CHANNEL_FROM_WINDOWSTATE is disabled. */ - InputChannel mInputChannel; + private InputChannel mInputChannel; /** * The token will be assigned to {@link InputWindowHandle#token} if this window can receive diff --git a/services/tests/InputMethodSystemServerTests/src/com/android/server/inputmethod/DefaultImeVisibilityApplierTest.java b/services/tests/InputMethodSystemServerTests/src/com/android/server/inputmethod/DefaultImeVisibilityApplierTest.java index 9e46f2f88561..8ae4f9a41efb 100644 --- a/services/tests/InputMethodSystemServerTests/src/com/android/server/inputmethod/DefaultImeVisibilityApplierTest.java +++ b/services/tests/InputMethodSystemServerTests/src/com/android/server/inputmethod/DefaultImeVisibilityApplierTest.java @@ -41,6 +41,7 @@ import static org.mockito.Mockito.when; import static java.util.Objects.requireNonNull; +import android.annotation.Nullable; import android.os.Binder; import android.os.IBinder; import android.os.RemoteException; @@ -50,6 +51,7 @@ import android.view.inputmethod.ImeTracker; import androidx.test.ext.junit.runners.AndroidJUnit4; import com.android.dx.mockito.inline.extended.ExtendedMockito; +import com.android.internal.annotations.GuardedBy; import com.android.internal.inputmethod.InputBindResult; import com.android.internal.inputmethod.SoftInputShowHideReason; import com.android.internal.inputmethod.StartInputFlags; @@ -70,15 +72,12 @@ import org.junit.runner.RunWith; public class DefaultImeVisibilityApplierTest extends InputMethodManagerServiceTestBase { private DefaultImeVisibilityApplier mVisibilityApplier; - private int mUserId = 0; - @Before public void setUp() throws RemoteException { super.setUp(); synchronized (ImfLock.class) { mVisibilityApplier = mInputMethodManagerService.getVisibilityApplierLocked(); - mUserId = mInputMethodManagerService.getCurrentImeUserIdLocked(); - mInputMethodManagerService.setAttachedClientForTesting(requireNonNull( + setAttachedClientLocked(requireNonNull( mInputMethodManagerService.getClientStateLocked(mMockInputMethodClient))); } } @@ -171,7 +170,9 @@ public class DefaultImeVisibilityApplierTest extends InputMethodManagerServiceTe // Init a IME target client on the secondary display to show IME. mInputMethodManagerService.addClient(mMockInputMethodClient, mMockRemoteInputConnection, 10 /* selfReportedDisplayId */); - mInputMethodManagerService.setAttachedClientForTesting(null); + synchronized (ImfLock.class) { + setAttachedClientLocked(null); + } startInputOrWindowGainedFocus(mWindowToken, SOFT_INPUT_STATE_ALWAYS_VISIBLE); final var statsToken = ImeTracker.Token.empty(); @@ -209,7 +210,9 @@ public class DefaultImeVisibilityApplierTest extends InputMethodManagerServiceTe @Test public void testApplyImeVisibility_hideImeWhenUnbinding() { - mInputMethodManagerService.setAttachedClientForTesting(null); + synchronized (ImfLock.class) { + setAttachedClientLocked(null); + } startInputOrWindowGainedFocus(mWindowToken, SOFT_INPUT_STATE_ALWAYS_VISIBLE); ExtendedMockito.spyOn(mVisibilityApplier); @@ -236,6 +239,11 @@ public class DefaultImeVisibilityApplierTest extends InputMethodManagerServiceTe } } + @GuardedBy("ImfLock.class") + private void setAttachedClientLocked(@Nullable ClientState cs) { + mInputMethodManagerService.getUserData(mUserId).mCurClient = cs; + } + private InputBindResult startInputOrWindowGainedFocus(IBinder windowToken, int softInputMode) { return mInputMethodManagerService.startInputOrWindowGainedFocus( StartInputReason.WINDOW_FOCUS_GAIN /* startInputReason */, @@ -248,7 +256,7 @@ public class DefaultImeVisibilityApplierTest extends InputMethodManagerServiceTe mMockRemoteInputConnection /* inputConnection */, mMockRemoteAccessibilityInputConnection /* remoteAccessibilityInputConnection */, mTargetSdkVersion /* unverifiedTargetSdkVersion */, - mCallingUserId /* userId */, + mUserId /* userId */, mMockImeOnBackInvokedDispatcher /* imeDispatcher */); } } diff --git a/services/tests/InputMethodSystemServerTests/src/com/android/server/inputmethod/ImeVisibilityStateComputerTest.java b/services/tests/InputMethodSystemServerTests/src/com/android/server/inputmethod/ImeVisibilityStateComputerTest.java index faa198ca41eb..dd3b33e0d12a 100644 --- a/services/tests/InputMethodSystemServerTests/src/com/android/server/inputmethod/ImeVisibilityStateComputerTest.java +++ b/services/tests/InputMethodSystemServerTests/src/com/android/server/inputmethod/ImeVisibilityStateComputerTest.java @@ -251,7 +251,7 @@ public class ImeVisibilityStateComputerTest extends InputMethodManagerServiceTes synchronized (ImfLock.class) { // Assume the last IME targeted window has requested IME visible final IBinder lastImeTargetWindowToken = new Binder(); - mInputMethodManagerService.mLastImeTargetWindow = lastImeTargetWindowToken; + mComputer.setLastImeTargetWindow(lastImeTargetWindowToken); mComputer.requestImeVisibility(lastImeTargetWindowToken, true); final ImeTargetWindowState lastState = mComputer.getWindowStateOrNull( lastImeTargetWindowToken); @@ -311,10 +311,8 @@ public class ImeVisibilityStateComputerTest extends InputMethodManagerServiceTes final ArgumentCaptor<IBinder> targetCaptor = ArgumentCaptor.forClass(IBinder.class); final ArgumentCaptor<ImeVisibilityResult> resultCaptor = ArgumentCaptor.forClass( ImeVisibilityResult.class); - synchronized (ImfLock.class) { - verify(mInputMethodManagerService).onApplyImeVisibilityFromComputerLocked( - targetCaptor.capture(), notNull() /* statsToken */, resultCaptor.capture()); - } + verify(mInputMethodManagerService).onApplyImeVisibilityFromComputerLocked( + targetCaptor.capture(), notNull() /* statsToken */, resultCaptor.capture()); final IBinder imeInputTarget = targetCaptor.getValue(); final ImeVisibilityResult result = resultCaptor.getValue(); diff --git a/services/tests/InputMethodSystemServerTests/src/com/android/server/inputmethod/ImmutableSparseArrayTest.java b/services/tests/InputMethodSystemServerTests/src/com/android/server/inputmethod/ImmutableSparseArrayTest.java new file mode 100644 index 000000000000..944b7c6d8e69 --- /dev/null +++ b/services/tests/InputMethodSystemServerTests/src/com/android/server/inputmethod/ImmutableSparseArrayTest.java @@ -0,0 +1,278 @@ +/* + * Copyright (C) 2024 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.android.server.inputmethod; + +import static com.google.common.truth.Truth.assertThat; + +import static org.junit.Assert.assertThrows; + +import android.annotation.NonNull; + +import androidx.test.ext.junit.runners.AndroidJUnit4; + +import org.junit.Test; +import org.junit.runner.RunWith; + +import java.util.ArrayList; + +@RunWith(AndroidJUnit4.class) +public final class ImmutableSparseArrayTest { + + @Test + public void testEmptyObject() { + final ImmutableSparseArray<Object> empty = ImmutableSparseArray.empty(); + + assertThat(empty.size()).isEqualTo(0); + verifyCommonBehaviors(empty); + } + + @Test + public void testEmptyMethod() { + assertThat(ImmutableSparseArray.empty()).isSameInstanceAs(ImmutableSparseArray.empty()); + } + + @Test + public void testCloneWithPutOrSelf_appendingFromEmpty() { + final int key1 = 1; + final Object value1 = new Object(); + final int key2 = -2; // intentionally negative + final Object value2 = new Object(); + final int key3 = -3; // intentionally negative + final Object value3 = new Object(); + final int key4 = 4; + final Object value4 = new Object(); + + final ImmutableSparseArray<Object> oneItemArray = ImmutableSparseArray.empty() + .cloneWithPutOrSelf(key1, value1); + verifyCommonBehaviors(oneItemArray); + assertThat(oneItemArray.size()).isEqualTo(1); + assertThat(oneItemArray.get(key1)).isSameInstanceAs(value1); + + final ImmutableSparseArray<Object> twoItemArray = + oneItemArray.cloneWithPutOrSelf(key2, value2); + assertThat(twoItemArray).isNotSameInstanceAs(oneItemArray); + verifyCommonBehaviors(twoItemArray); + assertThat(twoItemArray.size()).isEqualTo(2); + assertThat(twoItemArray.get(key1)).isSameInstanceAs(value1); + assertThat(twoItemArray.get(key2)).isSameInstanceAs(value2); + + final ImmutableSparseArray<Object> threeItemArray = + twoItemArray.cloneWithPutOrSelf(key3, value3); + assertThat(threeItemArray).isNotSameInstanceAs(twoItemArray); + verifyCommonBehaviors(threeItemArray); + assertThat(threeItemArray.size()).isEqualTo(3); + assertThat(threeItemArray.get(key1)).isSameInstanceAs(value1); + assertThat(threeItemArray.get(key2)).isSameInstanceAs(value2); + assertThat(threeItemArray.get(key3)).isSameInstanceAs(value3); + + final ImmutableSparseArray<Object> fourItemArray = + threeItemArray.cloneWithPutOrSelf(key4, value4); + assertThat(fourItemArray).isNotSameInstanceAs(threeItemArray); + verifyCommonBehaviors(fourItemArray); + assertThat(fourItemArray.size()).isEqualTo(4); + assertThat(fourItemArray.get(key1)).isSameInstanceAs(value1); + assertThat(fourItemArray.get(key2)).isSameInstanceAs(value2); + assertThat(fourItemArray.get(key3)).isSameInstanceAs(value3); + assertThat(fourItemArray.get(key4)).isSameInstanceAs(value4); + } + + @Test + public void testCloneWithPutOrSelf_returnSelf() { + final int key1 = 1; + final Object value1 = new Object(); + final ImmutableSparseArray<Object> array = ImmutableSparseArray + .empty() + .cloneWithPutOrSelf(key1, value1); + assertThat(array.cloneWithPutOrSelf(key1, value1)).isSameInstanceAs(array); + } + + @Test + public void testCloneWithPutOrSelf_updateExistingValue() { + final int key1 = 1; + final Object value1 = new Object(); + final int key2 = 2; + final Object value2 = new Object(); + final Object value2updated = new Object(); + final int key3 = 3; + final Object value3 = new Object(); + + final ImmutableSparseArray<Object> array = ImmutableSparseArray + .empty() + .cloneWithPutOrSelf(key1, value1) + .cloneWithPutOrSelf(key2, value2) + .cloneWithPutOrSelf(key3, value3); + + final var updatedArray = array.cloneWithPutOrSelf(key2, value2updated); + verifyCommonBehaviors(updatedArray); + + assertThat(updatedArray.size()).isEqualTo(3); + assertThat(updatedArray.get(key1)).isSameInstanceAs(value1); + assertThat(updatedArray.get(key2)).isSameInstanceAs(value2updated); + assertThat(updatedArray.get(key3)).isSameInstanceAs(value3); + } + + @Test + public void testCloneWithRemoveOrSelf_empty() { + final ImmutableSparseArray<Object> empty = ImmutableSparseArray.empty(); + assertThat(empty.cloneWithRemoveOrSelf(0)).isSameInstanceAs(empty); + } + + @Test + public void testCloneWithRemoveOrSelf_singleInstance() { + final int key = 1; + final Object value = new Object(); + final ImmutableSparseArray<Object> array = ImmutableSparseArray + .empty() + .cloneWithPutOrSelf(key, value); + assertThat(array.cloneWithRemoveOrSelf(key)).isSameInstanceAs(ImmutableSparseArray.empty()); + } + + @Test + public void testCloneWithRemoveOrSelf_firstItem() { + final int key1 = 1; + final Object value1 = new Object(); + final int key2 = 2; + final Object value2 = new Object(); + final int key3 = 3; + final Object value3 = new Object(); + + final ImmutableSparseArray<Object> array = ImmutableSparseArray + .empty() + .cloneWithPutOrSelf(key1, value1) + .cloneWithPutOrSelf(key2, value2) + .cloneWithPutOrSelf(key3, value3) + .cloneWithRemoveOrSelf(key1); + verifyCommonBehaviors(array); + + assertThat(array.size()).isEqualTo(2); + assertThat(array.get(key1)).isNull(); + assertThat(array.get(key2)).isSameInstanceAs(value2); + assertThat(array.get(key3)).isSameInstanceAs(value3); + assertThat(array.keyAt(0)).isEqualTo(key2); + assertThat(array.keyAt(1)).isEqualTo(key3); + } + + @Test + public void testCloneWithRemoveOrSelf_lastItem() { + final int key1 = 1; + final Object value1 = new Object(); + final int key2 = 2; + final Object value2 = new Object(); + final int key3 = 3; + final Object value3 = new Object(); + + final ImmutableSparseArray<Object> array = ImmutableSparseArray + .empty() + .cloneWithPutOrSelf(key1, value1) + .cloneWithPutOrSelf(key2, value2) + .cloneWithPutOrSelf(key3, value3) + .cloneWithRemoveOrSelf(key3); + verifyCommonBehaviors(array); + + assertThat(array.size()).isEqualTo(2); + assertThat(array.get(key1)).isSameInstanceAs(value1); + assertThat(array.get(key2)).isSameInstanceAs(value2); + assertThat(array.get(key3)).isNull(); + } + + @Test + public void testCloneWithRemoveOrSelf_middleItem() { + final int key1 = 1; + final Object value1 = new Object(); + final int key2 = 2; + final Object value2 = new Object(); + final int key3 = 3; + final Object value3 = new Object(); + + final ImmutableSparseArray<Object> array = ImmutableSparseArray + .empty() + .cloneWithPutOrSelf(key1, value1) + .cloneWithPutOrSelf(key2, value2) + .cloneWithPutOrSelf(key3, value3) + .cloneWithRemoveOrSelf(key2); + verifyCommonBehaviors(array); + + assertThat(array.size()).isEqualTo(2); + assertThat(array.get(key1)).isSameInstanceAs(value1); + assertThat(array.get(key2)).isNull(); + assertThat(array.get(key3)).isSameInstanceAs(value3); + } + + @Test + public void testCloneWithRemoveOrSelf_nonExistentItem() { + final int key1 = 1; + final Object value1 = new Object(); + final int key2 = 2; + final Object value2 = new Object(); + final int key3 = 3; + final Object value3 = new Object(); + final int key4 = 4; + + final ImmutableSparseArray<Object> array = ImmutableSparseArray + .empty() + .cloneWithPutOrSelf(key1, value1) + .cloneWithPutOrSelf(key2, value2) + .cloneWithPutOrSelf(key3, value3); + + assertThat(array.cloneWithRemoveOrSelf(key4)).isSameInstanceAs(array); + } + + @Test + public void testForEach() { + final int key1 = 1; + final Object value1 = new Object(); + final int key2 = 2; + final Object value2 = new Object(); + final int key3 = 3; + final Object value3 = new Object(); + + final ImmutableSparseArray<Object> array = ImmutableSparseArray + .empty() + .cloneWithPutOrSelf(key1, value1) + .cloneWithPutOrSelf(key2, value2) + .cloneWithPutOrSelf(key3, value3); + + final ArrayList<Object> list = new ArrayList<>(); + array.forEach(list::add); + assertThat(list).containsExactlyElementsIn(new Object[]{ value1, value2, value3 }) + .inOrder(); + } + + + private void verifyCommonBehaviors(@NonNull ImmutableSparseArray<Object> sparseArray) { + verifyInvalidKeyBehaviors(sparseArray); + verifyOutOfBoundsBehaviors(sparseArray); + } + + private void verifyInvalidKeyBehaviors(@NonNull ImmutableSparseArray<Object> sparseArray) { + final int invalid_key = -123456678; + assertThat(sparseArray.get(invalid_key)).isNull(); + assertThat(sparseArray.indexOfKey(invalid_key)).isEqualTo(-1); + } + + private void verifyOutOfBoundsBehaviors(@NonNull ImmutableSparseArray<Object> sparseArray) { + final int size = sparseArray.size(); + assertThrows(ArrayIndexOutOfBoundsException.class, + () -> sparseArray.keyAt(size)); + assertThrows(ArrayIndexOutOfBoundsException.class, + () -> sparseArray.valueAt(size)); + assertThrows(ArrayIndexOutOfBoundsException.class, + () -> sparseArray.keyAt(-1)); + assertThrows(ArrayIndexOutOfBoundsException.class, + () -> sparseArray.valueAt(-1)); + } +} diff --git a/services/tests/InputMethodSystemServerTests/src/com/android/server/inputmethod/InputMethodBindingControllerTest.java b/services/tests/InputMethodSystemServerTests/src/com/android/server/inputmethod/InputMethodBindingControllerTest.java index 4d28b3c854ff..1e3b7e9e05f4 100644 --- a/services/tests/InputMethodSystemServerTests/src/com/android/server/inputmethod/InputMethodBindingControllerTest.java +++ b/services/tests/InputMethodSystemServerTests/src/com/android/server/inputmethod/InputMethodBindingControllerTest.java @@ -140,8 +140,7 @@ public class InputMethodBindingControllerTest extends InputMethodManagerServiceT final InputMethodInfo info; synchronized (ImfLock.class) { mBindingController.setSelectedMethodId(TEST_IME_ID); - info = InputMethodSettingsRepository.get(mCallingUserId).getMethodMap() - .get(TEST_IME_ID); + info = InputMethodSettingsRepository.get(mUserId).getMethodMap().get(TEST_IME_ID); } assertThat(info).isNotNull(); assertThat(info.getId()).isEqualTo(TEST_IME_ID); diff --git a/services/tests/InputMethodSystemServerTests/src/com/android/server/inputmethod/InputMethodManagerServiceTestBase.java b/services/tests/InputMethodSystemServerTests/src/com/android/server/inputmethod/InputMethodManagerServiceTestBase.java index ec9bfa7200c6..461697cfa7cf 100644 --- a/services/tests/InputMethodSystemServerTests/src/com/android/server/inputmethod/InputMethodManagerServiceTestBase.java +++ b/services/tests/InputMethodSystemServerTests/src/com/android/server/inputmethod/InputMethodManagerServiceTestBase.java @@ -50,7 +50,6 @@ import android.os.IBinder; import android.os.Process; import android.os.RemoteException; import android.os.ServiceManager; -import android.os.UserHandle; import android.util.ArraySet; import android.view.InputChannel; import android.view.inputmethod.EditorInfo; @@ -128,7 +127,7 @@ public class InputMethodManagerServiceTestBase { protected Context mContext; protected MockitoSession mMockingSession; protected int mTargetSdkVersion; - protected int mCallingUserId; + protected int mUserId; protected EditorInfo mEditorInfo; protected IInputMethodInvoker mMockInputMethodInvoker; protected InputMethodManagerService mInputMethodManagerService; @@ -165,12 +164,12 @@ public class InputMethodManagerServiceTestBase { .spyStatic(AdditionalSubtypeUtils.class) .startMocking(); - mContext = spy(InstrumentationRegistry.getInstrumentation().getContext()); + mContext = spy(InstrumentationRegistry.getInstrumentation().getTargetContext()); mTargetSdkVersion = mContext.getApplicationInfo().targetSdkVersion; mIsLargeScreen = mContext.getResources().getConfiguration() .isLayoutSizeAtLeast(Configuration.SCREENLAYOUT_SIZE_LARGE); - mCallingUserId = UserHandle.getCallingUserId(); + mUserId = mContext.getUserId(); mEditorInfo = new EditorInfo(); mEditorInfo.packageName = TEST_EDITOR_PKG_NAME; @@ -202,7 +201,7 @@ public class InputMethodManagerServiceTestBase { // Injecting and mocked InputMethodBindingController and InputMethod. mMockInputMethodInvoker = IInputMethodInvoker.create(mMockInputMethod); mInputManagerGlobalSession = InputManagerGlobal.createTestSession(mMockIInputManager); - when(mMockInputMethodBindingController.getUserId()).thenReturn(mCallingUserId); + when(mMockInputMethodBindingController.getUserId()).thenReturn(mUserId); synchronized (ImfLock.class) { when(mMockInputMethodBindingController.getCurMethod()) .thenReturn(mMockInputMethodInvoker); @@ -222,7 +221,7 @@ public class InputMethodManagerServiceTestBase { .thenReturn(new int[] {0}); when(mMockUserManagerInternal.getUserIds()).thenReturn(new int[] {0}); when(mMockActivityManagerInternal.isSystemReady()).thenReturn(true); - when(mMockActivityManagerInternal.getCurrentUserId()).thenReturn(mCallingUserId); + when(mMockActivityManagerInternal.getCurrentUserId()).thenReturn(mUserId); when(mMockPackageManagerInternal.getPackageUid(anyString(), anyLong(), anyInt())) .thenReturn(Binder.getCallingUid()); when(mMockPackageManagerInternal.isSameApp(anyString(), anyLong(), anyInt(), anyInt())) @@ -272,14 +271,13 @@ public class InputMethodManagerServiceTestBase { // Certain tests rely on TEST_IME_ID that is installed with AndroidTest.xml. // TODO(b/352615651): Consider just synthesizing test InputMethodInfo then injecting it. - AdditionalSubtypeMapRepository.ensureInitializedAndGet(mCallingUserId); + AdditionalSubtypeMapRepository.initializeIfNecessary(mUserId); final var settings = InputMethodManagerService.queryInputMethodServicesInternal(mContext, - mCallingUserId, AdditionalSubtypeMapRepository.get(mCallingUserId), - DirectBootAwareness.AUTO); - InputMethodSettingsRepository.put(mCallingUserId, settings); + mUserId, AdditionalSubtypeMapRepository.get(mUserId), DirectBootAwareness.AUTO); + InputMethodSettingsRepository.put(mUserId, settings); // Emulate that the user initialization is done. - mInputMethodManagerService.getUserData(mCallingUserId).mBackgroundLoadLatch.countDown(); + mInputMethodManagerService.getUserData(mUserId).mBackgroundLoadLatch.countDown(); // After this boot phase, services can broadcast Intents. lifecycle.onBootPhase(SystemService.PHASE_ACTIVITY_MANAGER_READY); @@ -291,7 +289,7 @@ public class InputMethodManagerServiceTestBase { @After public void tearDown() { - InputMethodSettingsRepository.remove(mCallingUserId); + InputMethodSettingsRepository.remove(mUserId); if (mInputMethodManagerService != null) { mInputMethodManagerService.mInputMethodDeviceConfigs.destroy(); @@ -347,8 +345,8 @@ public class InputMethodManagerServiceTestBase { synchronized (ImfLock.class) { ClientState cs = mInputMethodManagerService.getClientStateLocked(client); cs.mCurSession = new InputMethodManagerService.SessionState(cs, - mMockInputMethodInvoker, mMockInputMethodSession, mock( - InputChannel.class)); + mMockInputMethodInvoker, mMockInputMethodSession, mock(InputChannel.class), + mUserId); } } } diff --git a/services/tests/InputMethodSystemServerTests/src/com/android/server/inputmethod/InputMethodManagerServiceWindowGainedFocusTest.java b/services/tests/InputMethodSystemServerTests/src/com/android/server/inputmethod/InputMethodManagerServiceWindowGainedFocusTest.java index ffc4df8f2069..c5b5668c67bc 100644 --- a/services/tests/InputMethodSystemServerTests/src/com/android/server/inputmethod/InputMethodManagerServiceWindowGainedFocusTest.java +++ b/services/tests/InputMethodSystemServerTests/src/com/android/server/inputmethod/InputMethodManagerServiceWindowGainedFocusTest.java @@ -263,7 +263,7 @@ public class InputMethodManagerServiceWindowGainedFocusTest mMockRemoteInputConnection /* inputConnection */, mMockRemoteAccessibilityInputConnection /* remoteAccessibilityInputConnection */, mTargetSdkVersion /* unverifiedTargetSdkVersion */, - mCallingUserId /* userId */, + mUserId /* userId */, mMockImeOnBackInvokedDispatcher /* imeDispatcher */); } diff --git a/services/tests/PackageManagerServiceTests/server/src/com/android/server/pm/PackageManagerServiceUtilsTest.java b/services/tests/PackageManagerServiceTests/server/src/com/android/server/pm/PackageManagerServiceUtilsTest.java new file mode 100644 index 000000000000..4a2396d195c1 --- /dev/null +++ b/services/tests/PackageManagerServiceTests/server/src/com/android/server/pm/PackageManagerServiceUtilsTest.java @@ -0,0 +1,341 @@ +/* + * Copyright (C) 2024 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.android.server.pm; + +import static org.testng.Assert.assertThrows; + +import android.content.pm.PackageInfoLite; +import android.platform.test.annotations.Presubmit; + +import androidx.test.ext.junit.runners.AndroidJUnit4; +import androidx.test.filters.SmallTest; +import androidx.test.platform.app.InstrumentationRegistry; + +import com.android.internal.pm.parsing.pkg.PackageImpl; +import com.android.server.pm.pkg.AndroidPackage; + +import org.junit.Test; +import org.junit.runner.RunWith; + +import java.io.File; +import java.util.UUID; + +@Presubmit +@RunWith(AndroidJUnit4.class) +@SmallTest +public class PackageManagerServiceUtilsTest { + + private static final String PACKAGE_NAME = "com.android.app"; + private static final File CODE_PATH = + InstrumentationRegistry.getInstrumentation().getContext().getFilesDir(); + + @Test + public void testCheckDowngrade_packageSetting_versionCodeSmaller_throwException() + throws Exception { + final PackageSetting before = createPackageSetting(); + before.setLongVersionCode(2); + final PackageInfoLite after = new PackageInfoLite(); + after.versionCode = 1; + + assertThrows(PackageManagerException.class, + () -> PackageManagerServiceUtils.checkDowngrade(before, after)); + } + + @Test + public void testCheckDowngrade_packageSetting_baseRevisionCodeSmaller_throwException() + throws Exception { + final PackageSetting before = createPackageSetting(); + before.setLongVersionCode(1); + before.setBaseRevisionCode(2); + final PackageInfoLite after = new PackageInfoLite(); + after.versionCode = 1; + after.baseRevisionCode = 1; + + assertThrows(PackageManagerException.class, + () -> PackageManagerServiceUtils.checkDowngrade(before, after)); + } + + @Test + public void testCheckDowngrade_packageSetting_splitArraySizeIsDifferent_throwException() + throws Exception { + final String splitOne = "one"; + final String splitTwo = "two"; + final int revisionOne = 311; + final int revisionTwo = 330; + final String[] splitNames = new String[] { splitOne, splitTwo }; + final int[] beforeSplitRevisionCodes = new int[] { revisionOne }; + final int[] afterSplitRevisionCodes = new int[] { revisionOne, revisionTwo }; + + final PackageSetting before = createPackageSetting(); + before.setLongVersionCode(1); + before.setSplitNames(splitNames); + before.setSplitRevisionCodes(beforeSplitRevisionCodes); + final PackageInfoLite after = new PackageInfoLite(); + after.versionCode = 1; + after.splitNames = splitNames; + after.splitRevisionCodes = afterSplitRevisionCodes; + + assertThrows(PackageManagerException.class, + () -> PackageManagerServiceUtils.checkDowngrade(before, after)); + } + + @Test + public void testCheckDowngrade_packageSetting_splitRevisionCodeSmaller_throwException() + throws Exception { + final String splitOne = "one"; + final String splitTwo = "two"; + final int revisionOne = 311; + final int revisionTwo = 330; + final int revisionThree = 360; + final String[] splitNames = new String[] { splitOne, splitTwo }; + final int[] beforeSplitRevisionCodes = new int[] { revisionTwo, revisionThree}; + final int[] afterSplitRevisionCodes = new int[] { revisionOne, revisionTwo }; + + final PackageSetting before = createPackageSetting(); + before.setLongVersionCode(1); + before.setSplitNames(splitNames); + before.setSplitRevisionCodes(beforeSplitRevisionCodes); + final PackageInfoLite after = new PackageInfoLite(); + after.versionCode = 1; + after.splitNames = splitNames; + after.splitRevisionCodes = afterSplitRevisionCodes; + + assertThrows(PackageManagerException.class, + () -> PackageManagerServiceUtils.checkDowngrade(before, after)); + } + + @Test + public void testCheckDowngrade_packageSetting_sameSplitNameRevisionsBigger() + throws Exception { + final String splitOne = "one"; + final String splitTwo = "two"; + final int revisionOne = 311; + final int revisionTwo = 330; + final int revisionThree = 360; + final String[] splitNames = new String[] { splitOne, splitTwo }; + final int[] beforeSplitRevisionCodes = new int[] { revisionOne, revisionTwo}; + final int[] afterSplitRevisionCodes = new int[] { revisionOne, revisionThree }; + + final PackageSetting before = createPackageSetting(); + before.setLongVersionCode(1); + before.setSplitNames(splitNames); + before.setSplitRevisionCodes(beforeSplitRevisionCodes); + final PackageInfoLite after = new PackageInfoLite(); + after.versionCode = 1; + after.splitNames = splitNames; + after.splitRevisionCodes = afterSplitRevisionCodes; + + PackageManagerServiceUtils.checkDowngrade(before, after); + } + + @Test + public void testCheckDowngrade_packageSetting_hasDifferentSplitNames() throws Exception { + final String splitOne = "one"; + final String splitTwo = "two"; + final int revisionOne = 311; + final int revisionTwo = 330; + final int revisionThree = 360; + final String[] beforeSplitNames = new String[] { splitOne, splitTwo }; + final String[] afterSplitNames = new String[] { splitTwo }; + final int[] beforeSplitRevisionCodes = new int[] { revisionOne, revisionTwo}; + final int[] afterSplitRevisionCodes = new int[] { revisionThree }; + + final PackageSetting before = createPackageSetting(); + before.setLongVersionCode(1); + before.setSplitNames(beforeSplitNames); + before.setSplitRevisionCodes(beforeSplitRevisionCodes); + final PackageInfoLite after = new PackageInfoLite(); + after.versionCode = 1; + after.splitNames = afterSplitNames; + after.splitRevisionCodes = afterSplitRevisionCodes; + + PackageManagerServiceUtils.checkDowngrade(before, after); + } + + @Test + public void testCheckDowngrade_packageSetting_newSplitName() throws Exception { + final String splitOne = "one"; + final String splitTwo = "two"; + final int revisionOne = 311; + final int revisionTwo = 330; + final String[] beforeSplitNames = new String[] { splitOne }; + final String[] afterSplitNames = new String[] { splitTwo }; + final int[] beforeSplitRevisionCodes = new int[] { revisionTwo }; + final int[] afterSplitRevisionCodes = new int[] { revisionOne }; + + final PackageSetting before = createPackageSetting(); + before.setLongVersionCode(1); + before.setSplitNames(beforeSplitNames); + before.setSplitRevisionCodes(beforeSplitRevisionCodes); + final PackageInfoLite after = new PackageInfoLite(); + after.versionCode = 1; + after.splitNames = afterSplitNames; + after.splitRevisionCodes = afterSplitRevisionCodes; + + PackageManagerServiceUtils.checkDowngrade(before, after); + } + + @Test + public void testCheckDowngrade_androidPackage_versionCodeSmaller_throwException() + throws Exception { + final AndroidPackage before = PackageImpl.forTesting(PACKAGE_NAME).hideAsParsed() + .setVersionCode(2).hideAsFinal(); + final PackageInfoLite after = new PackageInfoLite(); + after.versionCode = 1; + + assertThrows(PackageManagerException.class, + () -> PackageManagerServiceUtils.checkDowngrade(before, after)); + } + + @Test + public void testCheckDowngrade_androidPackage_baseRevisionCodeSmaller_throwException() + throws Exception { + final AndroidPackage before = PackageImpl.forTesting(PACKAGE_NAME).setBaseRevisionCode(2) + .hideAsParsed().setVersionCode(1).hideAsFinal(); + final PackageInfoLite after = new PackageInfoLite(); + after.versionCode = 1; + after.baseRevisionCode = 1; + + assertThrows(PackageManagerException.class, + () -> PackageManagerServiceUtils.checkDowngrade(before, after)); + } + + @Test + public void testCheckDowngrade_androidPackage_splitArraySizeIsDifferent_throwException() + throws Exception { + final String splitOne = "one"; + final String splitTwo = "two"; + final int revisionOne = 311; + final int revisionTwo = 330; + final String[] splitNames = new String[] { splitOne, splitTwo }; + final int[] beforeSplitRevisionCodes = new int[] { revisionOne }; + final int[] afterSplitRevisionCodes = new int[] { revisionOne, revisionTwo }; + + final AndroidPackage before = PackageImpl.forTesting(PACKAGE_NAME) + .asSplit(splitNames, /* splitCodePaths= */ null, + beforeSplitRevisionCodes, /* splitDependencies= */ null) + .hideAsParsed().setVersionCode(1).hideAsFinal(); + final PackageInfoLite after = new PackageInfoLite(); + after.versionCode = 1; + after.splitNames = splitNames; + after.splitRevisionCodes = afterSplitRevisionCodes; + + assertThrows(PackageManagerException.class, + () -> PackageManagerServiceUtils.checkDowngrade(before, after)); + } + + @Test + public void testCheckDowngrade_androidPackage_splitRevisionCodeSmaller_throwException() + throws Exception { + final String splitOne = "one"; + final String splitTwo = "two"; + final int revisionOne = 311; + final int revisionTwo = 330; + final int revisionThree = 360; + final String[] splitNames = new String[] { splitOne, splitTwo }; + final int[] beforeSplitRevisionCodes = new int[] { revisionTwo, revisionThree}; + final int[] afterSplitRevisionCodes = new int[] { revisionOne, revisionTwo }; + + final AndroidPackage before = PackageImpl.forTesting(PACKAGE_NAME) + .asSplit(splitNames, /* splitCodePaths= */ null, + beforeSplitRevisionCodes, /* splitDependencies= */ null) + .hideAsParsed().setVersionCode(1).hideAsFinal(); + final PackageInfoLite after = new PackageInfoLite(); + after.versionCode = 1; + after.splitNames = splitNames; + after.splitRevisionCodes = afterSplitRevisionCodes; + + assertThrows(PackageManagerException.class, + () -> PackageManagerServiceUtils.checkDowngrade(before, after)); + } + + @Test + public void testCheckDowngrade_androidPackage_sameSplitNameRevisionsBigger() + throws Exception { + final String splitOne = "one"; + final String splitTwo = "two"; + final int revisionOne = 311; + final int revisionTwo = 330; + final int revisionThree = 360; + final String[] splitNames = new String[] { splitOne, splitTwo }; + final int[] beforeSplitRevisionCodes = new int[] { revisionOne, revisionTwo}; + final int[] afterSplitRevisionCodes = new int[] { revisionOne, revisionThree }; + + final AndroidPackage before = PackageImpl.forTesting(PACKAGE_NAME) + .asSplit(splitNames, /* splitCodePaths= */ null, + beforeSplitRevisionCodes, /* splitDependencies= */ null) + .hideAsParsed().setVersionCode(1).hideAsFinal(); + final PackageInfoLite after = new PackageInfoLite(); + after.versionCode = 1; + after.splitNames = splitNames; + after.splitRevisionCodes = afterSplitRevisionCodes; + + PackageManagerServiceUtils.checkDowngrade(before, after); + } + + @Test + public void testCheckDowngrade_androidPackage_hasDifferentSplitNames() throws Exception { + final String splitOne = "one"; + final String splitTwo = "two"; + final int revisionOne = 311; + final int revisionTwo = 330; + final int revisionThree = 360; + final String[] beforeSplitNames = new String[] { splitOne, splitTwo }; + final String[] afterSplitNames = new String[] { splitTwo }; + final int[] beforeSplitRevisionCodes = new int[] { revisionOne, revisionTwo}; + final int[] afterSplitRevisionCodes = new int[] { revisionThree }; + + final AndroidPackage before = PackageImpl.forTesting(PACKAGE_NAME) + .asSplit(beforeSplitNames, /* splitCodePaths= */ null, + beforeSplitRevisionCodes, /* splitDependencies= */ null) + .hideAsParsed().setVersionCode(1).hideAsFinal(); + final PackageInfoLite after = new PackageInfoLite(); + after.versionCode = 1; + after.splitNames = afterSplitNames; + after.splitRevisionCodes = afterSplitRevisionCodes; + + PackageManagerServiceUtils.checkDowngrade(before, after); + } + + @Test + public void testCheckDowngrade_androidPackage_newSplitName() throws Exception { + final String splitOne = "one"; + final String splitTwo = "two"; + final int revisionOne = 311; + final int revisionTwo = 330; + final String[] beforeSplitNames = new String[] { splitOne }; + final String[] afterSplitNames = new String[] { splitTwo }; + final int[] beforeSplitRevisionCodes = new int[] { revisionTwo }; + final int[] afterSplitRevisionCodes = new int[] { revisionOne }; + + final AndroidPackage before = PackageImpl.forTesting(PACKAGE_NAME) + .asSplit(beforeSplitNames, /* splitCodePaths= */ null, + beforeSplitRevisionCodes, /* splitDependencies= */ null) + .hideAsParsed().setVersionCode(1).hideAsFinal(); + final PackageInfoLite after = new PackageInfoLite(); + after.versionCode = 1; + after.splitNames = afterSplitNames; + after.splitRevisionCodes = afterSplitRevisionCodes; + + PackageManagerServiceUtils.checkDowngrade(before, after); + } + + private PackageSetting createPackageSetting() { + return new PackageSetting(PACKAGE_NAME, PACKAGE_NAME, CODE_PATH, /* pkgFlags= */ 0, + /* privateFlags= */ 0 , UUID.randomUUID()); + } +} diff --git a/services/tests/PackageManagerServiceTests/server/src/com/android/server/pm/PackageManagerSettingsTests.java b/services/tests/PackageManagerServiceTests/server/src/com/android/server/pm/PackageManagerSettingsTests.java index dec463444faa..d7af443036bf 100644 --- a/services/tests/PackageManagerServiceTests/server/src/com/android/server/pm/PackageManagerSettingsTests.java +++ b/services/tests/PackageManagerServiceTests/server/src/com/android/server/pm/PackageManagerSettingsTests.java @@ -1092,7 +1092,7 @@ public class PackageManagerSettingsTests { } @Test - public void testNoPkg_writeReadSplitVersions() { + public void testNoPkgDifferentRevisions_writeReadSplitVersions() { Settings settings = makeSettings(); PackageSetting packageSetting = createPackageSetting(PACKAGE_NAME_1); packageSetting.setAppId(Process.FIRST_APPLICATION_UID); @@ -1117,6 +1117,54 @@ public class PackageManagerSettingsTests { } @Test + public void testNoPkgSameRevisions_writeReadSplitVersions() { + Settings settings = makeSettings(); + PackageSetting packageSetting = createPackageSetting(PACKAGE_NAME_1); + packageSetting.setAppId(Process.FIRST_APPLICATION_UID); + + final String splitOne = "one"; + final String splitTwo = "two"; + final int revisionOne = 311; + packageSetting.setSplitNames(new String[] { splitOne, splitTwo}); + packageSetting.setSplitRevisionCodes(new int[] { revisionOne, revisionOne}); + settings.mPackages.put(PACKAGE_NAME_1, packageSetting); + + settings.writeLPr(computer, /* sync= */ true); + settings.mPackages.clear(); + + assertThat(settings.readLPw(computer, createFakeUsers()), is(true)); + PackageSetting resultSetting = settings.getPackageLPr(PACKAGE_NAME_1); + assertThat(resultSetting.getSplitNames()[0], is(splitOne)); + assertThat(resultSetting.getSplitNames()[1], is(splitTwo)); + assertThat(resultSetting.getSplitRevisionCodes()[0], is(revisionOne)); + assertThat(resultSetting.getSplitRevisionCodes()[1], is(revisionOne)); + } + + @Test + public void testNoPkgSameSplitNames_writeReadSplitVersions() { + Settings settings = makeSettings(); + PackageSetting packageSetting = createPackageSetting(PACKAGE_NAME_1); + packageSetting.setAppId(Process.FIRST_APPLICATION_UID); + + final String splitOne = "one"; + final int revisionOne = 311; + final int revisionTwo = 330; + packageSetting.setSplitNames(new String[] { splitOne, splitOne}); + packageSetting.setSplitRevisionCodes(new int[] { revisionOne, revisionTwo}); + settings.mPackages.put(PACKAGE_NAME_1, packageSetting); + + settings.writeLPr(computer, /* sync= */ true); + settings.mPackages.clear(); + + assertThat(settings.readLPw(computer, createFakeUsers()), is(true)); + PackageSetting resultSetting = settings.getPackageLPr(PACKAGE_NAME_1); + assertThat(resultSetting.getSplitNames().length, is(1)); + assertThat(resultSetting.getSplitRevisionCodes().length, is(1)); + assertThat(resultSetting.getSplitNames()[0], is(splitOne)); + assertThat(resultSetting.getSplitRevisionCodes()[0], is(revisionTwo)); + } + + @Test public void testWriteReadArchiveState() { Settings settings = makeSettings(); PackageSetting packageSetting = createPackageSetting(PACKAGE_NAME_1); diff --git a/services/tests/displayservicetests/src/com/android/server/display/BrightnessMappingStrategyTest.java b/services/tests/displayservicetests/src/com/android/server/display/BrightnessMappingStrategyTest.java index fb73aff44c64..f3cd0c960fca 100644 --- a/services/tests/displayservicetests/src/com/android/server/display/BrightnessMappingStrategyTest.java +++ b/services/tests/displayservicetests/src/com/android/server/display/BrightnessMappingStrategyTest.java @@ -693,6 +693,21 @@ public class BrightnessMappingStrategyTest { } @Test + public void testGetPreset() { + int preset = Settings.System.SCREEN_BRIGHTNESS_AUTOMATIC_DIM; + Settings.System.putInt(mContext.getContentResolver(), + Settings.System.SCREEN_BRIGHTNESS_FOR_ALS, preset); + setUpResources(); + DisplayDeviceConfig ddc = new DdcBuilder() + .setAutoBrightnessLevels(AUTO_BRIGHTNESS_MODE_DEFAULT, preset, DISPLAY_LEVELS) + .setAutoBrightnessLevelsLux(AUTO_BRIGHTNESS_MODE_DEFAULT, preset, LUX_LEVELS) + .build(); + BrightnessMappingStrategy strategy = BrightnessMappingStrategy.create(mContext, ddc, + AUTO_BRIGHTNESS_MODE_DEFAULT, /* displayWhiteBalanceController= */ null); + assertEquals(preset, strategy.getPreset()); + } + + @Test public void testAutoBrightnessModeAndPreset() { int mode = AUTO_BRIGHTNESS_MODE_DOZE; int preset = Settings.System.SCREEN_BRIGHTNESS_AUTOMATIC_DIM; diff --git a/services/tests/displayservicetests/src/com/android/server/display/brightness/clamper/BrightnessLowLuxModifierTest.kt b/services/tests/displayservicetests/src/com/android/server/display/brightness/clamper/BrightnessLowLuxModifierTest.kt index d672435096b9..6929690baaf8 100644 --- a/services/tests/displayservicetests/src/com/android/server/display/brightness/clamper/BrightnessLowLuxModifierTest.kt +++ b/services/tests/displayservicetests/src/com/android/server/display/brightness/clamper/BrightnessLowLuxModifierTest.kt @@ -225,5 +225,37 @@ class BrightnessLowLuxModifierTest { assertThat(modifier.brightnessReason).isEqualTo(BrightnessReason.MODIFIER_MIN_LUX) assertThat(modifier.brightnessLowerBound).isEqualTo(LOW_LUX_BRIGHTNESS) } + + @Test + @RequiresFlagsEnabled(Flags.FLAG_EVEN_DIMMER) + fun testUserSwitch() { + // nits: 0.5 -> backlight 0.01 -> brightness -> 0.05 + whenever(mockDisplayDeviceConfig.getBacklightFromNits(/* nits= */ 0.5f)) + .thenReturn(0.01f) + whenever(mockDisplayDeviceConfig.getBrightnessFromBacklight(/* backlight = */ 0.01f)) + .thenReturn(0.05f) + + Settings.Secure.putIntForUser(context.contentResolver, + Settings.Secure.EVEN_DIMMER_ACTIVATED, 0, USER_ID) // off + Settings.Secure.putFloatForUser(context.contentResolver, + Settings.Secure.EVEN_DIMMER_MIN_NITS, 1.0f, USER_ID) + + modifier.recalculateLowerBound() + + assertThat(modifier.isActive).isFalse() + assertThat(modifier.brightnessLowerBound).isEqualTo(TRANSITION_POINT) + assertThat(modifier.brightnessReason).isEqualTo(0) // no reason - i.e. off + + Settings.Secure.putIntForUser(context.contentResolver, + Settings.Secure.EVEN_DIMMER_ACTIVATED, 1, USER_ID) // on + Settings.Secure.putFloatForUser(context.contentResolver, + Settings.Secure.EVEN_DIMMER_MIN_NITS, 0.5f, USER_ID) + modifier.onSwitchUser() + + assertThat(modifier.isActive).isTrue() + assertThat(modifier.brightnessReason).isEqualTo( + BrightnessReason.MODIFIER_MIN_USER_SET_LOWER_BOUND) + assertThat(modifier.brightnessLowerBound).isEqualTo(0.05f) + } } diff --git a/services/tests/displayservicetests/src/com/android/server/display/brightness/clamper/LightSensorControllerTest.kt b/services/tests/displayservicetests/src/com/android/server/display/brightness/clamper/LightSensorControllerTest.kt index f59e1275d2ce..79b99b5294d7 100644 --- a/services/tests/displayservicetests/src/com/android/server/display/brightness/clamper/LightSensorControllerTest.kt +++ b/services/tests/displayservicetests/src/com/android/server/display/brightness/clamper/LightSensorControllerTest.kt @@ -29,6 +29,7 @@ import com.android.server.display.config.SensorData import com.android.server.display.config.createSensorData import com.android.server.display.utils.AmbientFilter import org.junit.Before +import org.junit.Test import org.mockito.kotlin.any import org.mockito.kotlin.argumentCaptor import org.mockito.kotlin.eq @@ -62,31 +63,35 @@ class LightSensorControllerTest { mockLightSensorListener, mockHandler, testInjector) } - fun `does not register light sensor if is not configured`() { + @Test + fun doesNotRegisterLightSensorIfNotConfigured() { controller.restart() verifyNoMoreInteractions(mockSensorManager, mockAmbientFilter, mockLightSensorListener) } - fun `does not register light sensor if missing`() { + @Test + fun doesNotRegisterLightSensorIfMissing() { controller.configure(dummySensorData, DISPLAY_ID) controller.restart() verifyNoMoreInteractions(mockSensorManager, mockAmbientFilter, mockLightSensorListener) } - fun `register light sensor if configured and present`() { + @Test + fun registerLightSensorIfConfiguredAndPresent() { testInjector.lightSensor = TestUtils .createSensor(Sensor.TYPE_LIGHT, Sensor.STRING_TYPE_LIGHT) controller.configure(dummySensorData, DISPLAY_ID) controller.restart() verify(mockSensorManager).registerListener(any(), - testInjector.lightSensor, LIGHT_SENSOR_RATE * 1000, mockHandler) + eq(testInjector.lightSensor), eq(LIGHT_SENSOR_RATE * 1000), eq(mockHandler)) verifyNoMoreInteractions(mockSensorManager, mockAmbientFilter, mockLightSensorListener) } - fun `register light sensor once if not changed`() { + @Test + fun registerLightSensorOnceIfNotChanged() { testInjector.lightSensor = TestUtils .createSensor(Sensor.TYPE_LIGHT, Sensor.STRING_TYPE_LIGHT) controller.configure(dummySensorData, DISPLAY_ID) @@ -95,11 +100,12 @@ class LightSensorControllerTest { controller.restart() verify(mockSensorManager).registerListener(any(), - testInjector.lightSensor, LIGHT_SENSOR_RATE * 1000, mockHandler) + eq(testInjector.lightSensor), eq(LIGHT_SENSOR_RATE * 1000), eq(mockHandler)) verifyNoMoreInteractions(mockSensorManager, mockAmbientFilter, mockLightSensorListener) } - fun `register new light sensor and unregister old if changed`() { + @Test + fun registerNewAndUnregisterOldLightSensorIfChanged() { val lightSensor1 = TestUtils .createSensor(Sensor.TYPE_LIGHT, Sensor.STRING_TYPE_LIGHT) testInjector.lightSensor = lightSensor1 @@ -112,19 +118,21 @@ class LightSensorControllerTest { controller.configure(dummySensorData, DISPLAY_ID) controller.restart() - inOrder { + inOrder(mockSensorManager, mockAmbientFilter, mockLightSensorListener) { verify(mockSensorManager).registerListener(any(), - lightSensor1, LIGHT_SENSOR_RATE * 1000, mockHandler) - verify(mockSensorManager).unregisterListener(any<SensorEventListener>()) + eq(lightSensor1), eq(LIGHT_SENSOR_RATE * 1000), eq(mockHandler)) + verify(mockSensorManager).registerListener(any(), + eq(lightSensor2), eq(LIGHT_SENSOR_RATE * 1000), eq(mockHandler)) + verify(mockSensorManager).unregisterListener(any<SensorEventListener>(), + eq(lightSensor1)) verify(mockAmbientFilter).clear() verify(mockLightSensorListener).onAmbientLuxChange(LightSensorController.INVALID_LUX) - verify(mockSensorManager).registerListener(any(), - lightSensor2, LIGHT_SENSOR_RATE * 1000, mockHandler) } verifyNoMoreInteractions(mockSensorManager, mockAmbientFilter, mockLightSensorListener) } - fun `notifies listener on ambient lux change`() { + @Test + fun notifiesListenerOnAmbientLuxChange() { val expectedLux = 40f val eventLux = 50 val eventTime = 60L @@ -141,7 +149,7 @@ class LightSensorControllerTest { listener.onSensorChanged(TestUtils.createSensorEvent(testInjector.lightSensor, eventLux, eventTime * 1_000_000)) - inOrder { + inOrder(mockAmbientFilter, mockLightSensorListener) { verify(mockAmbientFilter).addValue(eventTime, eventLux.toFloat()) verify(mockLightSensorListener).onAmbientLuxChange(expectedLux) } diff --git a/services/tests/displayservicetests/src/com/android/server/display/mode/DisplayModeDirectorTest.java b/services/tests/displayservicetests/src/com/android/server/display/mode/DisplayModeDirectorTest.java index 242d5593c3c8..62400ebed149 100644 --- a/services/tests/displayservicetests/src/com/android/server/display/mode/DisplayModeDirectorTest.java +++ b/services/tests/displayservicetests/src/com/android/server/display/mode/DisplayModeDirectorTest.java @@ -1088,6 +1088,21 @@ public class DisplayModeDirectorTest { } @Test + public void testModeSwitching_UserSwitch() { + DisplayModeDirector director = createDirectorFromFpsRange(0, 90); + assertThat(director.getModeSwitchingType()).isEqualTo( + DisplayManager.SWITCHING_TYPE_WITHIN_GROUPS); + + int newModeSwitchingType = DisplayManager.SWITCHING_TYPE_NONE; + Settings.Secure.putInt(mContext.getContentResolver(), + Settings.Secure.MATCH_CONTENT_FRAME_RATE, newModeSwitchingType); + director.onSwitchUser(); + waitForIdleSync(); + + assertThat(director.getModeSwitchingType()).isEqualTo(newModeSwitchingType); + } + + @Test public void testDefaultDisplayModeIsSelectedIfAvailable() { final float[] refreshRates = new float[]{24f, 25f, 30f, 60f, 90f}; final int defaultModeId = 3; @@ -1883,6 +1898,62 @@ public class DisplayModeDirectorTest { } @Test + public void testPeakRefreshRate_UserSwitch() { + when(mDisplayManagerFlags.isBackUpSmoothDisplayAndForcePeakRefreshRateEnabled()) + .thenReturn(true); + DisplayModeDirector director = + new DisplayModeDirector(mContext, mHandler, mInjector, + mDisplayManagerFlags, mDisplayDeviceConfigProvider); + director.getBrightnessObserver().setDefaultDisplayState(Display.STATE_ON); + + Display.Mode[] modes1 = new Display.Mode[] { + new Display.Mode(/* modeId= */ 1, /* width= */ 1280, /* height= */ 720, + /* refreshRate= */ 60), + new Display.Mode(/* modeId= */ 2, /* width= */ 1280, /* height= */ 720, + /* refreshRate= */ 130), + }; + Display.Mode[] modes2 = new Display.Mode[] { + new Display.Mode(/* modeId= */ 1, /* width= */ 1280, /* height= */ 720, + /* refreshRate= */ 60), + new Display.Mode(/* modeId= */ 2, /* width= */ 1280, /* height= */ 720, + /* refreshRate= */ 140), + }; + SparseArray<Display.Mode[]> supportedModesByDisplay = new SparseArray<>(); + supportedModesByDisplay.put(DISPLAY_ID, modes1); + supportedModesByDisplay.put(DISPLAY_ID_2, modes2); + + Sensor lightSensor = createLightSensor(); + SensorManager sensorManager = createMockSensorManager(lightSensor); + director.start(sensorManager); + director.injectSupportedModesByDisplay(supportedModesByDisplay); + + // Disable Smooth Display + setPeakRefreshRate(RefreshRateSettingsUtils.DEFAULT_REFRESH_RATE); + + Vote vote1 = director.getVote(DISPLAY_ID, + Vote.PRIORITY_USER_SETTING_PEAK_RENDER_FRAME_RATE); + Vote vote2 = director.getVote(DISPLAY_ID_2, + Vote.PRIORITY_USER_SETTING_PEAK_RENDER_FRAME_RATE); + assertVoteForRenderFrameRateRange(vote1, /* frameRateLow= */ 0, + /* frameRateHigh= */ RefreshRateSettingsUtils.DEFAULT_REFRESH_RATE); + assertVoteForRenderFrameRateRange(vote2, /* frameRateLow= */ 0, + /* frameRateHigh= */ RefreshRateSettingsUtils.DEFAULT_REFRESH_RATE); + + // Switch user to one that has Smooth Display Enabled + Settings.System.putFloat(mContext.getContentResolver(), Settings.System.PEAK_REFRESH_RATE, + Float.POSITIVE_INFINITY); + director.onSwitchUser(); + waitForIdleSync(); + + vote1 = director.getVote(DISPLAY_ID, + Vote.PRIORITY_USER_SETTING_PEAK_RENDER_FRAME_RATE); + vote2 = director.getVote(DISPLAY_ID_2, + Vote.PRIORITY_USER_SETTING_PEAK_RENDER_FRAME_RATE); + assertVoteForRenderFrameRateRange(vote1, /* frameRateLow= */ 0, /* frameRateHigh= */ 130); + assertVoteForRenderFrameRateRange(vote2, /* frameRateLow= */ 0, /* frameRateHigh= */ 140); + } + + @Test @Parameters({ "true, true, 60", "false, true, 50", @@ -2036,6 +2107,62 @@ public class DisplayModeDirectorTest { } @Test + public void testMinRefreshRate_UserSwitch() { + when(mDisplayManagerFlags.isBackUpSmoothDisplayAndForcePeakRefreshRateEnabled()) + .thenReturn(true); + DisplayModeDirector director = + new DisplayModeDirector(mContext, mHandler, mInjector, + mDisplayManagerFlags, mDisplayDeviceConfigProvider); + director.getBrightnessObserver().setDefaultDisplayState(Display.STATE_ON); + + Display.Mode[] modes1 = new Display.Mode[] { + new Display.Mode(/* modeId= */ 1, /* width= */ 1280, /* height= */ 720, + /* refreshRate= */ 60), + new Display.Mode(/* modeId= */ 2, /* width= */ 1280, /* height= */ 720, + /* refreshRate= */ 130), + }; + Display.Mode[] modes2 = new Display.Mode[] { + new Display.Mode(/* modeId= */ 1, /* width= */ 1280, /* height= */ 720, + /* refreshRate= */ 60), + new Display.Mode(/* modeId= */ 2, /* width= */ 1280, /* height= */ 720, + /* refreshRate= */ 140), + }; + SparseArray<Display.Mode[]> supportedModesByDisplay = new SparseArray<>(); + supportedModesByDisplay.put(DISPLAY_ID, modes1); + supportedModesByDisplay.put(DISPLAY_ID_2, modes2); + + Sensor lightSensor = createLightSensor(); + SensorManager sensorManager = createMockSensorManager(lightSensor); + director.start(sensorManager); + director.injectSupportedModesByDisplay(supportedModesByDisplay); + + // Disable Force Peak Refresh Rate + setMinRefreshRate(0); + + Vote vote1 = director.getVote(DISPLAY_ID, Vote.PRIORITY_USER_SETTING_MIN_RENDER_FRAME_RATE); + Vote vote2 = director.getVote(DISPLAY_ID_2, + Vote.PRIORITY_USER_SETTING_MIN_RENDER_FRAME_RATE); + assertVoteForRenderFrameRateRange(vote1, /* frameRateLow= */ 0, + /* frameRateHigh= */ Float.POSITIVE_INFINITY); + assertVoteForRenderFrameRateRange(vote2, /* frameRateLow= */ 0, + /* frameRateHigh= */ Float.POSITIVE_INFINITY); + + // Switch user to one that has Force Peak Refresh Rate enabled + Settings.System.putFloat(mContext.getContentResolver(), Settings.System.MIN_REFRESH_RATE, + Float.POSITIVE_INFINITY); + director.onSwitchUser(); + waitForIdleSync(); + + vote1 = director.getVote(DISPLAY_ID, Vote.PRIORITY_USER_SETTING_MIN_RENDER_FRAME_RATE); + vote2 = director.getVote(DISPLAY_ID_2, + Vote.PRIORITY_USER_SETTING_MIN_RENDER_FRAME_RATE); + assertVoteForRenderFrameRateRange(vote1, /* frameRateLow= */ 130, + /* frameRateHigh= */ Float.POSITIVE_INFINITY); + assertVoteForRenderFrameRateRange(vote2, /* frameRateLow= */ 140, + /* frameRateHigh= */ Float.POSITIVE_INFINITY); + } + + @Test public void testPeakAndMinRefreshRate_FlagEnabled_DisplayWithOneMode() { when(mDisplayManagerFlags.isBackUpSmoothDisplayAndForcePeakRefreshRateEnabled()) .thenReturn(true); diff --git a/services/tests/mockingservicestests/src/com/android/server/pm/PackageArchiverTest.java b/services/tests/mockingservicestests/src/com/android/server/pm/PackageArchiverTest.java index 8d0b2797d200..fc28f9ef2a13 100644 --- a/services/tests/mockingservicestests/src/com/android/server/pm/PackageArchiverTest.java +++ b/services/tests/mockingservicestests/src/com/android/server/pm/PackageArchiverTest.java @@ -266,8 +266,8 @@ public class PackageArchiverTest { rule.mocks().getHandler().flush(); ArgumentCaptor<Intent> intentCaptor = ArgumentCaptor.forClass(Intent.class); - verify(mIntentSender).sendIntent(any(), anyInt(), intentCaptor.capture(), any(), any(), - any(), any()); + verify(mIntentSender).sendIntent(any(), anyInt(), intentCaptor.capture(), any(), + (Bundle) any(), any(), any()); Intent value = intentCaptor.getValue(); assertThat(value.getStringExtra(PackageInstaller.EXTRA_PACKAGE_NAME)).isEqualTo(PACKAGE); assertThat(value.getIntExtra(PackageInstaller.EXTRA_STATUS, 0)).isEqualTo( @@ -336,8 +336,8 @@ public class PackageArchiverTest { rule.mocks().getHandler().flush(); ArgumentCaptor<Intent> intentCaptor = ArgumentCaptor.forClass(Intent.class); - verify(mIntentSender).sendIntent(any(), anyInt(), intentCaptor.capture(), any(), any(), - any(), any()); + verify(mIntentSender).sendIntent(any(), anyInt(), intentCaptor.capture(), any(), + (Bundle) any(), any(), any()); Intent value = intentCaptor.getValue(); assertThat(value.getStringExtra(PackageInstaller.EXTRA_PACKAGE_NAME)).isEqualTo(PACKAGE); assertThat(value.getIntExtra(PackageInstaller.EXTRA_STATUS, 0)).isEqualTo( diff --git a/services/tests/performancehinttests/Android.bp b/services/tests/performancehinttests/Android.bp new file mode 100644 index 000000000000..1692921cdb2d --- /dev/null +++ b/services/tests/performancehinttests/Android.bp @@ -0,0 +1,34 @@ +package { + default_team: "trendy_team_games", + default_applicable_licenses: ["frameworks_base_license"], +} + +android_test { + name: "PerformanceHintTests", + srcs: [ + "src/**/*.java", + ], + static_libs: [ + "androidx.test.runner", + "androidx.test.rules", + "flag-junit", + "junit", + "mockito-target-minus-junit4", + "platform-test-annotations", + "services.core", + "truth", + ], + libs: [ + "android.test.base", + ], + test_suites: [ + "automotive-tests", + "device-tests", + ], + platform_apis: true, + certificate: "platform", + dxflags: ["--multi-dex"], + optimize: { + enabled: false, + }, +} diff --git a/services/tests/performancehinttests/AndroidManifest.xml b/services/tests/performancehinttests/AndroidManifest.xml new file mode 100644 index 000000000000..d9552344efc5 --- /dev/null +++ b/services/tests/performancehinttests/AndroidManifest.xml @@ -0,0 +1,23 @@ +<?xml version="1.0" encoding="utf-8"?> +<!-- Copyright (C) 2024 The Android Open Source Project + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. +--> + +<manifest xmlns:android="http://schemas.android.com/apk/res/android" + package="com.android.server.power.hinttests"> + + <instrumentation android:name="androidx.test.runner.AndroidJUnitRunner" + android:targetPackage="com.android.server.power.hinttests" + android:label="ADPF Performance Hint Service Test"/> +</manifest> diff --git a/services/tests/performancehinttests/AndroidTest.xml b/services/tests/performancehinttests/AndroidTest.xml new file mode 100644 index 000000000000..578b7d6ac5f1 --- /dev/null +++ b/services/tests/performancehinttests/AndroidTest.xml @@ -0,0 +1,34 @@ +<?xml version="1.0" encoding="utf-8"?> +<!-- Copyright (C) 2024 The Android Open Source Project + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. +--> +<configuration description="Runs Performance Hint Tests."> + <option name="test-suite-tag" value="apct" /> + <option name="test-suite-tag" value="apct-instrumentation" /> + + <target_preparer class="com.android.tradefed.targetprep.suite.SuiteApkInstaller"> + <option name="cleanup-apks" value="true" /> + <option name="install-arg" value="-t" /> + <option name="test-file-name" value="PerformanceHintTests.apk" /> + </target_preparer> + + <option name="test-tag" value="PerformanceHintTests" /> + + <test class="com.android.tradefed.testtype.AndroidJUnitTest" > + <option name="package" value="com.android.server.power.hinttests" /> + <option name="runner" value="androidx.test.runner.AndroidJUnitRunner" /> + <option name="hidden-api-checks" value="false"/> + <option name="exclude-annotation" value="androidx.test.filters.FlakyTest" /> + </test> +</configuration> diff --git a/services/tests/servicestests/src/com/android/server/power/hint/OWNERS b/services/tests/performancehinttests/OWNERS index c28c07a234b3..c28c07a234b3 100644 --- a/services/tests/servicestests/src/com/android/server/power/hint/OWNERS +++ b/services/tests/performancehinttests/OWNERS diff --git a/services/tests/performancehinttests/TEST_MAPPING b/services/tests/performancehinttests/TEST_MAPPING new file mode 100644 index 000000000000..fa7b89700952 --- /dev/null +++ b/services/tests/performancehinttests/TEST_MAPPING @@ -0,0 +1,19 @@ +{ + "presubmit": [ + { + "name": "PerformanceHintTests", + "options": [ + {"exclude-annotation": "org.junit.Ignore"} + ] + } + ], + "ravenwood-postsubmit": [ + { + "name": "PerformanceHintTestsRavenwood", + "host": true, + "options": [ + {"exclude-annotation": "android.platform.test.annotations.DisabledOnRavenwood"} + ] + } + ] +} diff --git a/services/tests/servicestests/src/com/android/server/power/hint/HintManagerServiceTest.java b/services/tests/performancehinttests/src/com/android/server/power/hint/HintManagerServiceTest.java index 1decd36be394..7d0447097375 100644 --- a/services/tests/servicestests/src/com/android/server/power/hint/HintManagerServiceTest.java +++ b/services/tests/performancehinttests/src/com/android/server/power/hint/HintManagerServiceTest.java @@ -596,7 +596,7 @@ public class HintManagerServiceTest { ActivityManager.PROCESS_STATE_IMPORTANT_FOREGROUND, 0, 0); service.mUidObserver.onUidStateChanged(UID, ActivityManager.PROCESS_STATE_IMPORTANT_BACKGROUND, 0, 0); - LockSupport.parkNanos(TimeUnit.MILLISECONDS.toNanos(500) + TimeUnit.MILLISECONDS.toNanos( + LockSupport.parkNanos(TimeUnit.MILLISECONDS.toNanos(1000) + TimeUnit.MILLISECONDS.toNanos( CLEAN_UP_UID_DELAY_MILLIS)); verify(mNativeWrapperMock, never()).halSetThreads(eq(sessionPtr1), any()); reset(mNativeWrapperMock); @@ -653,7 +653,7 @@ public class HintManagerServiceTest { ActivityManager.PROCESS_STATE_IMPORTANT_FOREGROUND, 0, 0); service.mUidObserver.onUidStateChanged(UID, ActivityManager.PROCESS_STATE_IMPORTANT_BACKGROUND, 0, 0); - LockSupport.parkNanos(TimeUnit.MILLISECONDS.toNanos(500) + TimeUnit.MILLISECONDS.toNanos( + LockSupport.parkNanos(TimeUnit.MILLISECONDS.toNanos(1000) + TimeUnit.MILLISECONDS.toNanos( CLEAN_UP_UID_DELAY_MILLIS)); verify(mNativeWrapperMock, never()).halSetThreads(eq(sessionPtr1), any()); verify(mNativeWrapperMock, never()).halSetThreads(eq(sessionPtr2), any()); @@ -666,7 +666,7 @@ public class HintManagerServiceTest { service.mUidObserver.onUidStateChanged(UID, ActivityManager.PROCESS_STATE_IMPORTANT_FOREGROUND, 0, 0); // wait for the async uid state change to trigger resume and setThreads - LockSupport.parkNanos(TimeUnit.MILLISECONDS.toNanos(500)); + LockSupport.parkNanos(TimeUnit.MILLISECONDS.toNanos(1000)); verify(mNativeWrapperMock, times(1)).halSetThreads(eq(sessionPtr2), eq(expectedTids2)); reset(mNativeWrapperMock); @@ -675,7 +675,7 @@ public class HintManagerServiceTest { LockSupport.parkNanos(TimeUnit.MILLISECONDS.toNanos(100)); service.mUidObserver.onUidStateChanged(UID, ActivityManager.PROCESS_STATE_IMPORTANT_BACKGROUND, 0, 0); - LockSupport.parkNanos(TimeUnit.MILLISECONDS.toNanos(500) + TimeUnit.MILLISECONDS.toNanos( + LockSupport.parkNanos(TimeUnit.MILLISECONDS.toNanos(1000) + TimeUnit.MILLISECONDS.toNanos( CLEAN_UP_UID_DELAY_MILLIS)); verify(mNativeWrapperMock, times(1)).halPauseHintSession(eq(sessionPtr1)); verify(mNativeWrapperMock, never()).halSetThreads(eq(sessionPtr1), any()); @@ -684,7 +684,7 @@ public class HintManagerServiceTest { verifyAllHintsEnabled(session2, false); service.mUidObserver.onUidStateChanged(UID, ActivityManager.PROCESS_STATE_IMPORTANT_FOREGROUND, 0, 0); - LockSupport.parkNanos(TimeUnit.MILLISECONDS.toNanos(500)); + LockSupport.parkNanos(TimeUnit.MILLISECONDS.toNanos(1000)); verifyAllHintsEnabled(session1, false); verifyAllHintsEnabled(session2, true); reset(mNativeWrapperMock); @@ -705,7 +705,7 @@ public class HintManagerServiceTest { LockSupport.parkNanos(TimeUnit.MILLISECONDS.toNanos(100)); service.mUidObserver.onUidStateChanged(UID, ActivityManager.PROCESS_STATE_IMPORTANT_BACKGROUND, 0, 0); - LockSupport.parkNanos(TimeUnit.MILLISECONDS.toNanos(500) + TimeUnit.MILLISECONDS.toNanos( + LockSupport.parkNanos(TimeUnit.MILLISECONDS.toNanos(1000) + TimeUnit.MILLISECONDS.toNanos( CLEAN_UP_UID_DELAY_MILLIS)); verify(mNativeWrapperMock, times(1)).halPauseHintSession(eq(sessionPtr1)); verify(mNativeWrapperMock, never()).halSetThreads(eq(sessionPtr1), any()); @@ -721,7 +721,7 @@ public class HintManagerServiceTest { service.mUidObserver.onUidStateChanged(UID, ActivityManager.PROCESS_STATE_IMPORTANT_FOREGROUND, 0, 0); - LockSupport.parkNanos(TimeUnit.MILLISECONDS.toNanos(500) + TimeUnit.MILLISECONDS.toNanos( + LockSupport.parkNanos(TimeUnit.MILLISECONDS.toNanos(1000) + TimeUnit.MILLISECONDS.toNanos( CLEAN_UP_UID_DELAY_MILLIS)); verify(mNativeWrapperMock, times(1)).halSetThreads(eq(sessionPtr1), eq(SESSION_TIDS_A)); diff --git a/services/tests/powerservicetests/src/com/android/server/power/NotifierTest.java b/services/tests/powerservicetests/src/com/android/server/power/NotifierTest.java index ce2bb95b790a..d45e31248d0b 100644 --- a/services/tests/powerservicetests/src/com/android/server/power/NotifierTest.java +++ b/services/tests/powerservicetests/src/com/android/server/power/NotifierTest.java @@ -44,6 +44,7 @@ import android.os.PowerManager; import android.os.RemoteException; import android.os.VibrationAttributes; import android.os.Vibrator; +import android.os.WorkSource; import android.os.test.TestLooper; import android.provider.Settings; import android.testing.TestableContext; @@ -60,6 +61,7 @@ import com.android.server.statusbar.StatusBarManagerInternal; import org.junit.Before; import org.junit.Test; import org.mockito.Mock; +import org.mockito.Mockito; import org.mockito.MockitoAnnotations; import java.util.concurrent.Executor; @@ -231,7 +233,7 @@ public class NotifierTest { } @Test - public void testOnWakeLockListener_RemoteException_NoRethrow() { + public void testOnWakeLockListener_RemoteException_NoRethrow() throws RemoteException { when(mPowerManagerFlags.improveWakelockLatency()).thenReturn(true); createNotifier(); clearInvocations(mWakeLockLog, mBatteryStats, mAppOpsManager); @@ -249,33 +251,58 @@ public class NotifierTest { verifyZeroInteractions(mWakeLockLog); mTestLooper.dispatchAll(); verify(mWakeLockLog).onWakeLockReleased("wakelockTag", uid, 1); - + clearInvocations(mBatteryStats); mNotifier.onWakeLockAcquired(PowerManager.PARTIAL_WAKE_LOCK, "wakelockTag", "my.package.name", uid, pid, /* workSource= */ null, /* historyTag= */ null, exceptingCallback); + + verifyNoMoreInteractions(mWakeLockLog, mBatteryStats); + mTestLooper.dispatchAll(); + verify(mWakeLockLog).onWakeLockAcquired("wakelockTag", uid, + PowerManager.PARTIAL_WAKE_LOCK, 1); + verify(mBatteryStats).noteStartWakelock(uid, pid, "wakelockTag", /* historyTag= */ null, + BatteryStats.WAKE_TYPE_PARTIAL, false); + + verifyNoMoreInteractions(mWakeLockLog, mBatteryStats); + WorkSource worksourceOld = Mockito.mock(WorkSource.class); + WorkSource worksourceNew = Mockito.mock(WorkSource.class); + mNotifier.onWakeLockChanging(PowerManager.PARTIAL_WAKE_LOCK, "wakelockTag", - "my.package.name", uid, pid, /* workSource= */ null, /* historyTag= */ null, + "my.package.name", uid, pid, worksourceOld, /* historyTag= */ null, exceptingCallback, PowerManager.SCREEN_BRIGHT_WAKE_LOCK, "wakelockTag", - "my.package.name", uid, pid, /* newWorkSource= */ null, /* newHistoryTag= */ null, + "my.package.name", uid, pid, worksourceNew, /* newHistoryTag= */ null, exceptingCallback); - verifyNoMoreInteractions(mWakeLockLog); mTestLooper.dispatchAll(); - verify(mWakeLockLog).onWakeLockAcquired("wakelockTag", uid, - PowerManager.PARTIAL_WAKE_LOCK, 1); + verify(mBatteryStats).noteChangeWakelockFromSource(worksourceOld, pid, "wakelockTag", + null, BatteryStats.WAKE_TYPE_PARTIAL, worksourceNew, pid, "wakelockTag", + null, BatteryStats.WAKE_TYPE_FULL, false); // If we didn't throw, we're good! // Test with improveWakelockLatency flag false, hence the wakelock log will run on the same // thread - clearInvocations(mWakeLockLog); + clearInvocations(mWakeLockLog, mBatteryStats); when(mPowerManagerFlags.improveWakelockLatency()).thenReturn(false); + // Acquire the wakelock mNotifier.onWakeLockAcquired(PowerManager.PARTIAL_WAKE_LOCK, "wakelockTag", "my.package.name", uid, pid, /* workSource= */ null, /* historyTag= */ null, exceptingCallback); verify(mWakeLockLog).onWakeLockAcquired("wakelockTag", uid, PowerManager.PARTIAL_WAKE_LOCK, -1); + // Update the wakelock + mNotifier.onWakeLockChanging(PowerManager.PARTIAL_WAKE_LOCK, "wakelockTag", + "my.package.name", uid, pid, worksourceOld, /* historyTag= */ null, + exceptingCallback, + PowerManager.SCREEN_BRIGHT_WAKE_LOCK, "wakelockTag", + "my.package.name", uid, pid, worksourceNew, /* newHistoryTag= */ null, + exceptingCallback); + verify(mBatteryStats).noteChangeWakelockFromSource(worksourceOld, pid, "wakelockTag", + null, BatteryStats.WAKE_TYPE_PARTIAL, worksourceNew, pid, "wakelockTag", + null, BatteryStats.WAKE_TYPE_FULL, false); + + // Release the wakelock mNotifier.onWakeLockReleased(PowerManager.PARTIAL_WAKE_LOCK, "wakelockTag", "my.package.name", uid, pid, /* workSource= */ null, /* historyTag= */ null, exceptingCallback); diff --git a/services/tests/powerservicetests/src/com/android/server/power/PowerManagerServiceTest.java b/services/tests/powerservicetests/src/com/android/server/power/PowerManagerServiceTest.java index b737e0f98317..40c521a1dc64 100644 --- a/services/tests/powerservicetests/src/com/android/server/power/PowerManagerServiceTest.java +++ b/services/tests/powerservicetests/src/com/android/server/power/PowerManagerServiceTest.java @@ -1304,6 +1304,7 @@ public class PowerManagerServiceTest { .setDozeOverrideFromDreamManager( Display.STATE_ON, Display.STATE_REASON_DEFAULT_POLICY, + PowerManager.BRIGHTNESS_INVALID_FLOAT, PowerManager.BRIGHTNESS_DEFAULT); assertTrue(isAcquired[0]); } diff --git a/services/tests/powerstatstests/src/com/android/server/power/stats/SensorPowerStatsProcessorTest.java b/services/tests/powerstatstests/src/com/android/server/power/stats/SensorPowerStatsProcessorTest.java new file mode 100644 index 000000000000..7000487e7912 --- /dev/null +++ b/services/tests/powerstatstests/src/com/android/server/power/stats/SensorPowerStatsProcessorTest.java @@ -0,0 +1,241 @@ +/* + * Copyright (C) 2024 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.android.server.power.stats; + +import static android.os.BatteryConsumer.PROCESS_STATE_BACKGROUND; +import static android.os.BatteryConsumer.PROCESS_STATE_CACHED; +import static android.os.BatteryConsumer.PROCESS_STATE_FOREGROUND; +import static android.os.BatteryConsumer.PROCESS_STATE_FOREGROUND_SERVICE; + +import static com.android.server.power.stats.AggregatedPowerStatsConfig.POWER_STATE_OTHER; +import static com.android.server.power.stats.AggregatedPowerStatsConfig.SCREEN_STATE_ON; +import static com.android.server.power.stats.AggregatedPowerStatsConfig.SCREEN_STATE_OTHER; +import static com.android.server.power.stats.AggregatedPowerStatsConfig.STATE_POWER; +import static com.android.server.power.stats.AggregatedPowerStatsConfig.STATE_PROCESS_STATE; +import static com.android.server.power.stats.AggregatedPowerStatsConfig.STATE_SCREEN; + +import static com.google.common.truth.Truth.assertThat; + +import static org.mockito.Mockito.mock; +import static org.mockito.Mockito.when; + +import android.hardware.Sensor; +import android.hardware.SensorManager; +import android.hardware.input.InputSensorInfo; +import android.os.BatteryConsumer; +import android.os.BatteryStats; +import android.os.Process; +import android.platform.test.ravenwood.RavenwoodRule; + +import com.android.internal.os.MonotonicClock; +import com.android.internal.os.PowerStats; + +import org.junit.Before; +import org.junit.Rule; +import org.junit.Test; +import org.mockito.Mock; +import org.mockito.MockitoAnnotations; + +import java.util.List; + +public class SensorPowerStatsProcessorTest { + @Rule(order = 0) + public final RavenwoodRule mRavenwood = new RavenwoodRule.Builder() + .setProvideMainThread(true) + .build(); + + @Rule(order = 1) + public final BatteryUsageStatsRule mStatsRule = new BatteryUsageStatsRule() + .initMeasuredEnergyStatsLocked(); + + private static final double PRECISION = 0.00001; + private static final int APP_UID1 = Process.FIRST_APPLICATION_UID + 42; + private static final int APP_UID2 = Process.FIRST_APPLICATION_UID + 101; + private static final int SENSOR_HANDLE_1 = 77; + private static final int SENSOR_HANDLE_2 = 88; + private static final int SENSOR_HANDLE_3 = 99; + + @Mock + private SensorManager mSensorManager; + + private MonotonicClock mMonotonicClock; + + @Before + public void setup() { + MockitoAnnotations.initMocks(this); + mMonotonicClock = new MonotonicClock(0, mStatsRule.getMockClock()); + Sensor sensor1 = createSensor(SENSOR_HANDLE_1, Sensor.TYPE_STEP_COUNTER, + Sensor.STRING_TYPE_STEP_COUNTER, "dancing", 100); + Sensor sensor2 = createSensor(SENSOR_HANDLE_2, Sensor.TYPE_MOTION_DETECT, + "com.example", "tango", 200); + Sensor sensor3 = createSensor(SENSOR_HANDLE_3, Sensor.TYPE_MOTION_DETECT, + "com.example", "waltz", 300); + when(mSensorManager.getSensorList(Sensor.TYPE_ALL)).thenReturn( + List.of(sensor1, sensor2, sensor3)); + } + + @Test + public void testPowerEstimation() { + SensorPowerStatsProcessor processor = new SensorPowerStatsProcessor(() -> mSensorManager); + + PowerComponentAggregatedPowerStats stats = createAggregatedPowerStats(processor); + + processor.noteStateChange(stats, buildHistoryItem(0, true, APP_UID1, SENSOR_HANDLE_1)); + + // Turn the screen off after 2.5 seconds + stats.setState(STATE_SCREEN, SCREEN_STATE_OTHER, 2500); + stats.setUidState(APP_UID1, STATE_PROCESS_STATE, PROCESS_STATE_BACKGROUND, 2500); + stats.setUidState(APP_UID1, STATE_PROCESS_STATE, PROCESS_STATE_FOREGROUND_SERVICE, 5000); + + processor.noteStateChange(stats, buildHistoryItem(6000, false, APP_UID1, SENSOR_HANDLE_1)); + processor.noteStateChange(stats, buildHistoryItem(7000, true, APP_UID2, SENSOR_HANDLE_1)); + processor.noteStateChange(stats, buildHistoryItem(8000, true, APP_UID2, SENSOR_HANDLE_2)); + processor.noteStateChange(stats, buildHistoryItem(9000, false, APP_UID2, SENSOR_HANDLE_1)); + + processor.finish(stats, 10000); + + PowerStats.Descriptor descriptor = stats.getPowerStatsDescriptor(); + SensorPowerStatsLayout statsLayout = new SensorPowerStatsLayout(); + statsLayout.fromExtras(descriptor.extras); + + String dump = stats.toString(); + assertThat(dump).contains(" step_counter: "); + assertThat(dump).contains(" com.example.tango: "); + + long[] uidStats = new long[descriptor.uidStatsArrayLength]; + + // For UID1: + // SENSOR1 was on for 6000 ms. + // Estimated power: 6000 * 100 = 0.167 mAh + // split between three different states + // fg screen-on: 6000 * 2500/10000 + // bg screen-off: 6000 * 2500/10000 + // fgs screen-off: 6000 * 5000/10000 + double expectedPower1 = 0.166666; + stats.getUidStats(uidStats, APP_UID1, + states(POWER_STATE_OTHER, SCREEN_STATE_ON, PROCESS_STATE_FOREGROUND)); + assertThat(statsLayout.getUidPowerEstimate(uidStats)) + .isWithin(PRECISION).of(expectedPower1 * 2500 / 10000); + stats.getUidStats(uidStats, APP_UID1, + states(POWER_STATE_OTHER, SCREEN_STATE_OTHER, PROCESS_STATE_BACKGROUND)); + assertThat(statsLayout.getUidPowerEstimate(uidStats)) + .isWithin(PRECISION).of(expectedPower1 * 2500 / 10000); + stats.getUidStats(uidStats, APP_UID1, + states(POWER_STATE_OTHER, SCREEN_STATE_OTHER, PROCESS_STATE_FOREGROUND_SERVICE)); + assertThat(statsLayout.getUidPowerEstimate(uidStats)) + .isWithin(PRECISION).of(expectedPower1 * 5000 / 10000); + + // For UID2: + // SENSOR1 was on for 2000 ms. + // Estimated power: 2000 * 100 = 0.0556 mAh + // split between three different states + // cached screen-on: 2000 * 2500/10000 + // cached screen-off: 2000 * 7500/10000 + // SENSOR2 was on for 2000 ms. + // Estimated power: 2000 * 200 = 0.11111 mAh + // split between three different states + // cached screen-on: 2000 * 2500/10000 + // cached screen-off: 2000 * 7500/10000 + double expectedPower2 = 0.05555 + 0.11111; + stats.getUidStats(uidStats, APP_UID2, + states(POWER_STATE_OTHER, SCREEN_STATE_ON, PROCESS_STATE_CACHED)); + assertThat(statsLayout.getUidPowerEstimate(uidStats)) + .isWithin(PRECISION).of(expectedPower2 * 2500 / 10000); + stats.getUidStats(uidStats, APP_UID2, + states(POWER_STATE_OTHER, SCREEN_STATE_OTHER, PROCESS_STATE_CACHED)); + assertThat(statsLayout.getUidPowerEstimate(uidStats)) + .isWithin(PRECISION).of(expectedPower2 * 7500 / 10000); + + long[] deviceStats = new long[descriptor.statsArrayLength]; + + stats.getDeviceStats(deviceStats, states(POWER_STATE_OTHER, SCREEN_STATE_ON)); + assertThat(statsLayout.getDevicePowerEstimate(deviceStats)) + .isWithin(PRECISION).of((expectedPower1 + expectedPower2) * 2500 / 10000); + + stats.getDeviceStats(deviceStats, states(POWER_STATE_OTHER, SCREEN_STATE_OTHER)); + assertThat(statsLayout.getDevicePowerEstimate(deviceStats)) + .isWithin(PRECISION).of((expectedPower1 + expectedPower2) * 7500 / 10000); + } + + private BatteryStats.HistoryItem buildHistoryItem(int timestamp, boolean stateOn, + int uid, int sensor) { + mStatsRule.setTime(timestamp, timestamp); + BatteryStats.HistoryItem historyItem = new BatteryStats.HistoryItem(); + historyItem.time = mMonotonicClock.monotonicTime(); + historyItem.states = stateOn ? BatteryStats.HistoryItem.STATE_SENSOR_ON_FLAG : 0; + if (stateOn) { + historyItem.eventCode = BatteryStats.HistoryItem.EVENT_STATE_CHANGE + | BatteryStats.HistoryItem.EVENT_FLAG_START; + } else { + historyItem.eventCode = BatteryStats.HistoryItem.EVENT_STATE_CHANGE + | BatteryStats.HistoryItem.EVENT_FLAG_FINISH; + } + historyItem.eventTag = historyItem.localEventTag; + historyItem.eventTag.uid = uid; + historyItem.eventTag.string = "sensor:0x" + Integer.toHexString(sensor); + return historyItem; + } + + private int[] states(int... states) { + return states; + } + + private static PowerComponentAggregatedPowerStats createAggregatedPowerStats( + SensorPowerStatsProcessor processor) { + AggregatedPowerStatsConfig config = new AggregatedPowerStatsConfig(); + config.trackPowerComponent(BatteryConsumer.POWER_COMPONENT_SENSORS) + .trackDeviceStates( + AggregatedPowerStatsConfig.STATE_POWER, + AggregatedPowerStatsConfig.STATE_SCREEN) + .trackUidStates( + AggregatedPowerStatsConfig.STATE_POWER, + AggregatedPowerStatsConfig.STATE_SCREEN, + AggregatedPowerStatsConfig.STATE_PROCESS_STATE) + .setProcessor(processor); + + AggregatedPowerStats aggregatedPowerStats = new AggregatedPowerStats(config); + PowerComponentAggregatedPowerStats powerComponentStats = + aggregatedPowerStats.getPowerComponentStats( + BatteryConsumer.POWER_COMPONENT_SENSORS); + processor.start(powerComponentStats, 0); + + powerComponentStats.setState(STATE_POWER, POWER_STATE_OTHER, 0); + powerComponentStats.setState(STATE_SCREEN, SCREEN_STATE_ON, 0); + powerComponentStats.setUidState(APP_UID1, STATE_PROCESS_STATE, PROCESS_STATE_FOREGROUND, 0); + powerComponentStats.setUidState(APP_UID2, STATE_PROCESS_STATE, PROCESS_STATE_CACHED, 0); + + return powerComponentStats; + } + + private Sensor createSensor(int handle, int type, String stringType, String name, float power) { + if (RavenwoodRule.isOnRavenwood()) { + Sensor sensor = mock(Sensor.class); + when(sensor.getHandle()).thenReturn(handle); + when(sensor.getType()).thenReturn(type); + when(sensor.getStringType()).thenReturn(stringType); + when(sensor.getName()).thenReturn(name); + when(sensor.getPower()).thenReturn(power); + return sensor; + } else { + return new Sensor(new InputSensorInfo(name, "vendor", 0 /* version */, + handle, type, 100.0f /*maxRange */, 0.02f /* resolution */, + (float) power, 1000 /* minDelay */, 0 /* fifoReservedEventCount */, + 0 /* fifoMaxEventCount */, stringType /* stringType */, + "" /* requiredPermission */, 0 /* maxDelay */, 0 /* flags */, 0 /* id */)); + } + } +} diff --git a/services/tests/servicestests/Android.bp b/services/tests/servicestests/Android.bp index a888dadff5c6..a86289b317d0 100644 --- a/services/tests/servicestests/Android.bp +++ b/services/tests/servicestests/Android.bp @@ -78,7 +78,6 @@ android_test { // TODO: remove once Android migrates to JUnit 4.12, // which provides assertThrows "testng", - "truth", "junit", "junit-params", "ActivityContext", diff --git a/services/tests/servicestests/src/com/android/server/accessibility/AccessibilityManagerServiceTest.java b/services/tests/servicestests/src/com/android/server/accessibility/AccessibilityManagerServiceTest.java index 20b9592cb9f2..1afe12fc6927 100644 --- a/services/tests/servicestests/src/com/android/server/accessibility/AccessibilityManagerServiceTest.java +++ b/services/tests/servicestests/src/com/android/server/accessibility/AccessibilityManagerServiceTest.java @@ -840,6 +840,10 @@ public class AccessibilityManagerServiceTest { info_a.setComponentName(COMPONENT_NAME); final AccessibilityServiceInfo info_b = new AccessibilityServiceInfo(); info_b.setComponentName(new ComponentName("package", "class")); + writeStringsToSetting(Set.of( + info_a.getComponentName().flattenToString(), + info_b.getComponentName().flattenToString()), + Settings.Secure.ENABLED_ACCESSIBILITY_SERVICES); AccessibilityUserState userState = mA11yms.getCurrentUserState(); userState.mInstalledServices.clear(); @@ -858,10 +862,9 @@ public class AccessibilityManagerServiceTest { userState = mA11yms.getCurrentUserState(); assertThat(userState.mEnabledServices).containsExactly(info_b.getComponentName()); //Assert setting change - final Set<ComponentName> componentsFromSetting = new ArraySet<>(); - mA11yms.readComponentNamesFromSettingLocked(Settings.Secure.ENABLED_ACCESSIBILITY_SERVICES, - userState.mUserId, componentsFromSetting); - assertThat(componentsFromSetting).containsExactly(info_b.getComponentName()); + final Set<String> enabledServices = + readStringsFromSetting(Settings.Secure.ENABLED_ACCESSIBILITY_SERVICES); + assertThat(enabledServices).containsExactly(info_b.getComponentName().flattenToString()); } @Test @@ -880,6 +883,10 @@ public class AccessibilityManagerServiceTest { info_a.getComponentName().flattenToString(), info_b.getComponentName().flattenToString()), SOFTWARE); + writeStringsToSetting(Set.of( + info_a.getComponentName().flattenToString(), + info_b.getComponentName().flattenToString()), + ShortcutUtils.convertToKey(SOFTWARE)); // despite force stopping both packages, only the first service has the relevant flag, // so only the first should be removed. @@ -896,13 +903,53 @@ public class AccessibilityManagerServiceTest { assertThat(userState.getShortcutTargetsLocked(SOFTWARE)).containsExactly( info_b.getComponentName().flattenToString()); //Assert setting change - final Set<String> targetsFromSetting = new ArraySet<>(); - mA11yms.readColonDelimitedSettingToSet(ShortcutUtils.convertToKey(SOFTWARE), - userState.mUserId, str -> str, targetsFromSetting); + final Set<String> targetsFromSetting = readStringsFromSetting( + ShortcutUtils.convertToKey(SOFTWARE)); assertThat(targetsFromSetting).containsExactly(info_b.getComponentName().flattenToString()); } @Test + public void testPackagesForceStopped_otherServiceStopped_doesNotRemoveContinuousTarget() { + final AccessibilityServiceInfo info_a = new AccessibilityServiceInfo(); + info_a.setComponentName(COMPONENT_NAME); + info_a.flags = FLAG_REQUEST_ACCESSIBILITY_BUTTON; + final AccessibilityServiceInfo info_b = new AccessibilityServiceInfo(); + info_b.setComponentName(new ComponentName("package", "class")); + writeStringsToSetting(Set.of( + info_a.getComponentName().flattenToString(), + info_b.getComponentName().flattenToString()), + ShortcutUtils.convertToKey(SOFTWARE)); + + AccessibilityUserState userState = mA11yms.getCurrentUserState(); + userState.mInstalledServices.clear(); + userState.mInstalledServices.add(info_a); + userState.mInstalledServices.add(info_b); + userState.updateShortcutTargetsLocked(Set.of( + info_a.getComponentName().flattenToString(), + info_b.getComponentName().flattenToString()), + SOFTWARE); + + // Force stopping a service should not disable unrelated continuous services. + synchronized (mA11yms.getLock()) { + mA11yms.onPackagesForceStoppedLocked( + new String[]{info_b.getComponentName().getPackageName()}, + userState); + } + + //Assert user state change + userState = mA11yms.getCurrentUserState(); + assertThat(userState.getShortcutTargetsLocked(SOFTWARE)).containsExactly( + info_a.getComponentName().flattenToString(), + info_b.getComponentName().flattenToString()); + //Assert setting unchanged + final Set<String> targetsFromSetting = readStringsFromSetting( + ShortcutUtils.convertToKey(SOFTWARE)); + assertThat(targetsFromSetting).containsExactly( + info_a.getComponentName().flattenToString(), + info_b.getComponentName().flattenToString()); + } + + @Test public void testPackageMonitorScanPackages_scansWithoutHoldingLock() { setupAccessibilityServiceConnection(0); final AtomicReference<Set<Boolean>> lockState = collectLockStateWhilePackageScanning(); @@ -1844,6 +1891,11 @@ public class AccessibilityManagerServiceTest { return result; } + private void writeStringsToSetting(Set<String> strings, String setting) { + mA11yms.persistColonDelimitedSetToSettingLocked( + setting, UserHandle.USER_SYSTEM, strings, str -> str); + } + private void broadcastSettingRestored(String setting, String newValue) { Intent intent = new Intent(Intent.ACTION_SETTING_RESTORED) .addFlags(Intent.FLAG_RECEIVER_REGISTERED_ONLY) diff --git a/services/tests/servicestests/src/com/android/server/accessibility/a11ychecker/AccessibilityCheckerManagerTest.java b/services/tests/servicestests/src/com/android/server/accessibility/a11ychecker/AccessibilityCheckerManagerTest.java index f92eaabab3f7..c1b3929d3cba 100644 --- a/services/tests/servicestests/src/com/android/server/accessibility/a11ychecker/AccessibilityCheckerManagerTest.java +++ b/services/tests/servicestests/src/com/android/server/accessibility/a11ychecker/AccessibilityCheckerManagerTest.java @@ -18,13 +18,13 @@ package com.android.server.accessibility.a11ychecker; import static com.android.server.accessibility.Flags.FLAG_ENABLE_A11Y_CHECKER_LOGGING; import static com.android.server.accessibility.a11ychecker.AccessibilityCheckerConstants.MIN_DURATION_BETWEEN_CHECKS; +import static com.android.server.accessibility.a11ychecker.TestUtils.QUALIFIED_TEST_ACTIVITY_NAME; import static com.android.server.accessibility.a11ychecker.TestUtils.TEST_A11Y_SERVICE_CLASS_NAME; import static com.android.server.accessibility.a11ychecker.TestUtils.TEST_A11Y_SERVICE_SOURCE_PACKAGE_NAME; import static com.android.server.accessibility.a11ychecker.TestUtils.TEST_ACTIVITY_NAME; import static com.android.server.accessibility.a11ychecker.TestUtils.TEST_DEFAULT_BROWSER; import static com.android.server.accessibility.a11ychecker.TestUtils.createAtom; import static com.android.server.accessibility.a11ychecker.TestUtils.getMockPackageManagerWithInstalledApps; -import static com.android.server.accessibility.a11ychecker.TestUtils.getTestAccessibilityEvent; import static com.google.common.truth.Truth.assertThat; @@ -114,7 +114,7 @@ public class AccessibilityCheckerManagerTest { Set<A11yCheckerProto.AccessibilityCheckResultReported> results = mAccessibilityCheckerManager.maybeRunA11yChecker( - List.of(mockNodeInfo1, mockNodeInfo2), getTestAccessibilityEvent(), + List.of(mockNodeInfo1, mockNodeInfo2), QUALIFIED_TEST_ACTIVITY_NAME, new ComponentName(TEST_A11Y_SERVICE_SOURCE_PACKAGE_NAME, TEST_A11Y_SERVICE_CLASS_NAME), /*userId=*/ 0); @@ -139,7 +139,7 @@ public class AccessibilityCheckerManagerTest { Set<A11yCheckerProto.AccessibilityCheckResultReported> results = mAccessibilityCheckerManager.maybeRunA11yChecker( - List.of(mockNodeInfo), getTestAccessibilityEvent(), + List.of(mockNodeInfo), QUALIFIED_TEST_ACTIVITY_NAME, new ComponentName(TEST_A11Y_SERVICE_SOURCE_PACKAGE_NAME, TEST_A11Y_SERVICE_CLASS_NAME), /*userId=*/ 0); @@ -160,7 +160,7 @@ public class AccessibilityCheckerManagerTest { Set<A11yCheckerProto.AccessibilityCheckResultReported> results = mAccessibilityCheckerManager.maybeRunA11yChecker( - List.of(mockNodeInfo, mockNodeInfoDuplicate), getTestAccessibilityEvent(), + List.of(mockNodeInfo, mockNodeInfoDuplicate), QUALIFIED_TEST_ACTIVITY_NAME, new ComponentName(TEST_A11Y_SERVICE_SOURCE_PACKAGE_NAME, TEST_A11Y_SERVICE_CLASS_NAME), /*userId=*/ 0); diff --git a/services/tests/servicestests/src/com/android/server/accessibility/a11ychecker/AccessibilityCheckerUtilsTest.java b/services/tests/servicestests/src/com/android/server/accessibility/a11ychecker/AccessibilityCheckerUtilsTest.java index 141f174e9615..5b4e72e0ea45 100644 --- a/services/tests/servicestests/src/com/android/server/accessibility/a11ychecker/AccessibilityCheckerUtilsTest.java +++ b/services/tests/servicestests/src/com/android/server/accessibility/a11ychecker/AccessibilityCheckerUtilsTest.java @@ -16,11 +16,13 @@ package com.android.server.accessibility.a11ychecker; +import static com.android.server.accessibility.a11ychecker.TestUtils.QUALIFIED_TEST_ACTIVITY_NAME; import static com.android.server.accessibility.a11ychecker.TestUtils.TEST_A11Y_SERVICE_CLASS_NAME; import static com.android.server.accessibility.a11ychecker.TestUtils.TEST_A11Y_SERVICE_SOURCE_PACKAGE_NAME; +import static com.android.server.accessibility.a11ychecker.TestUtils.TEST_ACTIVITY_NAME; +import static com.android.server.accessibility.a11ychecker.TestUtils.TEST_APP_PACKAGE_NAME; import static com.android.server.accessibility.a11ychecker.TestUtils.createAtom; import static com.android.server.accessibility.a11ychecker.TestUtils.getMockPackageManagerWithInstalledApps; -import static com.android.server.accessibility.a11ychecker.TestUtils.getTestAccessibilityEvent; import static com.google.common.truth.Truth.assertThat; @@ -28,7 +30,6 @@ import static org.mockito.Mockito.when; import android.content.ComponentName; import android.content.pm.PackageManager; -import android.view.accessibility.AccessibilityEvent; import android.view.accessibility.AccessibilityNodeInfo; import androidx.test.runner.AndroidJUnit4; @@ -138,11 +139,15 @@ public class AccessibilityCheckerUtilsTest { } @Test - public void getActivityName_hasWindowStateChangedEvent_returnsActivityName() { - AccessibilityEvent accessibilityEvent = getTestAccessibilityEvent(); + public void getActivityName_hasValidActivityClassName_returnsActivityName() { + assertThat(AccessibilityCheckerUtils.getActivityName(mMockPackageManager, + TEST_APP_PACKAGE_NAME, QUALIFIED_TEST_ACTIVITY_NAME)).isEqualTo(TEST_ACTIVITY_NAME); + } + @Test + public void getActivityName_hasInvalidActivityClassName_returnsActivityName() { assertThat(AccessibilityCheckerUtils.getActivityName(mMockPackageManager, - accessibilityEvent)).isEqualTo("MainActivity"); + TEST_APP_PACKAGE_NAME, "com.NonActivityClass")).isEmpty(); } // Makes sure the AccessibilityHierarchyCheck class to enum mapping is up to date with the diff --git a/services/tests/servicestests/src/com/android/server/accessibility/a11ychecker/TestUtils.java b/services/tests/servicestests/src/com/android/server/accessibility/a11ychecker/TestUtils.java index ec1a25554a81..acf64b62c7d9 100644 --- a/services/tests/servicestests/src/com/android/server/accessibility/a11ychecker/TestUtils.java +++ b/services/tests/servicestests/src/com/android/server/accessibility/a11ychecker/TestUtils.java @@ -16,6 +16,7 @@ package com.android.server.accessibility.a11ychecker; +import static org.mockito.ArgumentMatchers.eq; import static org.mockito.Mockito.anyInt; import static org.mockito.Mockito.when; @@ -26,6 +27,7 @@ import android.content.pm.PackageInfo; import android.content.pm.PackageManager; import android.view.accessibility.AccessibilityEvent; +import org.mockito.AdditionalMatchers; import org.mockito.Mockito; public class TestUtils { @@ -46,8 +48,11 @@ public class TestUtils { ComponentName testActivityComponentName = new ComponentName(TEST_APP_PACKAGE_NAME, QUALIFIED_TEST_ACTIVITY_NAME); - when(mockPackageManager.getActivityInfo(testActivityComponentName, 0)) + when(mockPackageManager.getActivityInfo(eq(testActivityComponentName), eq(0))) .thenReturn(testActivityInfo); + when(mockPackageManager.getActivityInfo( + AdditionalMatchers.not(eq(testActivityComponentName)), eq(0))) + .thenThrow(PackageManager.NameNotFoundException.class); when(mockPackageManager.getPackageInfo(TEST_APP_PACKAGE_NAME, 0)) .thenReturn(createPackageInfo(TEST_APP_PACKAGE_NAME, TEST_APP_VERSION_CODE, testActivityInfo)); diff --git a/services/tests/servicestests/src/com/android/server/accessibility/magnification/FullScreenMagnificationGestureHandlerTest.java b/services/tests/servicestests/src/com/android/server/accessibility/magnification/FullScreenMagnificationGestureHandlerTest.java index 3ef81fde6506..60bcecc2f885 100644 --- a/services/tests/servicestests/src/com/android/server/accessibility/magnification/FullScreenMagnificationGestureHandlerTest.java +++ b/services/tests/servicestests/src/com/android/server/accessibility/magnification/FullScreenMagnificationGestureHandlerTest.java @@ -620,7 +620,7 @@ public class FullScreenMagnificationGestureHandlerTest { @Test @RequiresFlagsEnabled(Flags.FLAG_ENABLE_MAGNIFICATION_MULTIPLE_FINGER_MULTIPLE_TAP_GESTURE) - public void testTwoFingerTap_StateIsActivated_shouldInDelegating() { + public void testTwoFingerTap_StateIsActivated_shouldInDetecting() { assumeTrue(isWatch()); enableOneFingerPanning(false); goFromStateIdleTo(STATE_ACTIVATED); @@ -629,14 +629,15 @@ public class FullScreenMagnificationGestureHandlerTest { send(downEvent()); send(pointerEvent(ACTION_POINTER_DOWN, DEFAULT_X * 2, DEFAULT_Y)); send(upEvent()); - fastForward(ViewConfiguration.getDoubleTapTimeout()); + fastForward(mMgh.mDetectingState.mMultiTapMaxDelay); - assertTrue(mMgh.mCurrentState == mMgh.mDelegatingState); + verify(mMgh.getNext(), times(3)).onMotionEvent(any(), any(), anyInt()); + assertTrue(mMgh.mCurrentState == mMgh.mDetectingState); } @Test @RequiresFlagsEnabled(Flags.FLAG_ENABLE_MAGNIFICATION_MULTIPLE_FINGER_MULTIPLE_TAP_GESTURE) - public void testTwoFingerTap_StateIsIdle_shouldInDelegating() { + public void testTwoFingerTap_StateIsIdle_shouldInDetecting() { assumeTrue(isWatch()); enableOneFingerPanning(false); goFromStateIdleTo(STATE_IDLE); @@ -645,9 +646,10 @@ public class FullScreenMagnificationGestureHandlerTest { send(downEvent()); send(pointerEvent(ACTION_POINTER_DOWN, DEFAULT_X * 2, DEFAULT_Y)); send(upEvent()); - fastForward(ViewConfiguration.getDoubleTapTimeout()); + fastForward(mMgh.mDetectingState.mMultiTapMaxDelay); - assertTrue(mMgh.mCurrentState == mMgh.mDelegatingState); + verify(mMgh.getNext(), times(3)).onMotionEvent(any(), any(), anyInt()); + assertTrue(mMgh.mCurrentState == mMgh.mDetectingState); } @Test @@ -982,6 +984,53 @@ public class FullScreenMagnificationGestureHandlerTest { } @Test + public void testSingleFingerOverscrollAtTopEdge_isWatch_scrollDiagonally_noOverscroll() { + assumeTrue(isWatch()); + goFromStateIdleTo(STATE_SINGLE_PANNING); + float centerX = + (INITIAL_MAGNIFICATION_BOUNDS.right + INITIAL_MAGNIFICATION_BOUNDS.left) / 2.0f; + mFullScreenMagnificationController.setCenter( + DISPLAY_0, centerX, INITIAL_MAGNIFICATION_BOUNDS.top, false, 1); + final float swipeMinDistance = ViewConfiguration.get(mContext).getScaledTouchSlop() + 1; + PointF initCoords = + new PointF( + mFullScreenMagnificationController.getCenterX(DISPLAY_0), + mFullScreenMagnificationController.getCenterY(DISPLAY_0)); + PointF edgeCoords = new PointF(initCoords.x, initCoords.y); + // Scroll diagonally towards top-right with a bigger right delta + edgeCoords.offset(swipeMinDistance * 2, swipeMinDistance); + + swipeAndHold(initCoords, edgeCoords); + + assertTrue(mMgh.mOverscrollHandler.mOverscrollState == mMgh.OVERSCROLL_NONE); + assertTrue(isZoomed()); + } + + @Test + public void + testSingleFingerOverscrollAtTopEdge_isWatch_scrollDiagonally_expectedOverscrollState() { + assumeTrue(isWatch()); + goFromStateIdleTo(STATE_SINGLE_PANNING); + float centerX = + (INITIAL_MAGNIFICATION_BOUNDS.right + INITIAL_MAGNIFICATION_BOUNDS.left) / 2.0f; + mFullScreenMagnificationController.setCenter( + DISPLAY_0, centerX, INITIAL_MAGNIFICATION_BOUNDS.top, false, 1); + final float swipeMinDistance = ViewConfiguration.get(mContext).getScaledTouchSlop() + 1; + PointF initCoords = + new PointF( + mFullScreenMagnificationController.getCenterX(DISPLAY_0), + mFullScreenMagnificationController.getCenterY(DISPLAY_0)); + PointF edgeCoords = new PointF(initCoords.x, initCoords.y); + // Scroll diagonally towards top-right with a bigger top delta + edgeCoords.offset(swipeMinDistance, swipeMinDistance * 2); + + swipeAndHold(initCoords, edgeCoords); + + assertTrue(mMgh.mOverscrollHandler.mOverscrollState == mMgh.OVERSCROLL_VERTICAL_EDGE); + assertTrue(isZoomed()); + } + + @Test public void testSingleFingerScrollAtEdge_isWatch_noOverscroll() { assumeTrue(isWatch()); goFromStateIdleTo(STATE_SINGLE_PANNING); @@ -1057,9 +1106,24 @@ public class FullScreenMagnificationGestureHandlerTest { assumeTrue(isWatch()); goFromStateIdleTo(STATE_ACTIVATED); - swipeAndHold(); + PointF pointer = DEFAULT_POINT; + send(downEvent(pointer.x, pointer.y)); + + // first move triggers the panning state + pointer.offset(100, 100); + fastForward(20); + send(moveEvent(pointer.x, pointer.y)); + + // second move actually pans + pointer.offset(100, 100); + fastForward(20); + send(moveEvent(pointer.x, pointer.y)); + pointer.offset(100, 100); + fastForward(20); + send(moveEvent(pointer.x, pointer.y)); + fastForward(20); - swipe(DEFAULT_POINT, new PointF(DEFAULT_X * 2, DEFAULT_Y * 2), /* durationMs= */ 20); + send(upEvent(pointer.x, pointer.y)); verify(mMockScroller).fling( /* startX= */ anyInt(), diff --git a/services/tests/servicestests/src/com/android/server/appop/DiscreteAppOpPersistenceTest.java b/services/tests/servicestests/src/com/android/server/appop/DiscreteAppOpPersistenceTest.java new file mode 100644 index 000000000000..bc3a5ca6f7e6 --- /dev/null +++ b/services/tests/servicestests/src/com/android/server/appop/DiscreteAppOpPersistenceTest.java @@ -0,0 +1,168 @@ +/* + * Copyright (C) 2024 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.android.server.appop; + +import static android.app.AppOpsManager.ATTRIBUTION_FLAG_ACCESSOR; +import static android.app.AppOpsManager.ATTRIBUTION_FLAG_RECEIVER; +import static android.app.AppOpsManager.OP_FLAGS_ALL_TRUSTED; +import static android.app.AppOpsManager.OP_FLAG_SELF; +import static android.app.AppOpsManager.UID_STATE_FOREGROUND; +import static android.app.AppOpsManager.UID_STATE_FOREGROUND_SERVICE; + +import static com.google.common.truth.Truth.assertThat; + +import android.app.AppOpsManager; +import android.companion.virtual.VirtualDeviceManager; +import android.content.Context; +import android.os.FileUtils; +import android.os.Process; +import android.permission.flags.Flags; +import android.platform.test.annotations.RequiresFlagsEnabled; +import android.platform.test.flag.junit.CheckFlagsRule; +import android.platform.test.flag.junit.DeviceFlagsValueProvider; + +import androidx.test.ext.junit.runners.AndroidJUnit4; +import androidx.test.platform.app.InstrumentationRegistry; + +import org.junit.After; +import org.junit.Before; +import org.junit.Rule; +import org.junit.Test; +import org.junit.runner.RunWith; + +import java.io.File; +import java.util.List; + +@RunWith(AndroidJUnit4.class) +public class DiscreteAppOpPersistenceTest { + private DiscreteRegistry mDiscreteRegistry; + private final Object mLock = new Object(); + private File mMockDataDirectory; + private final Context mContext = + InstrumentationRegistry.getInstrumentation().getTargetContext(); + + @Rule + public final CheckFlagsRule mCheckFlagsRule = DeviceFlagsValueProvider.createCheckFlagsRule(); + + @Before + public void setUp() { + mMockDataDirectory = mContext.getDir("mock_data", Context.MODE_PRIVATE); + mDiscreteRegistry = new DiscreteRegistry(mLock, mMockDataDirectory); + mDiscreteRegistry.systemReady(); + } + + @After + public void cleanUp() { + mDiscreteRegistry.writeAndClearAccessHistory(); + FileUtils.deleteContents(mMockDataDirectory); + } + + @RequiresFlagsEnabled(Flags.FLAG_DEVICE_AWARE_APP_OP_NEW_SCHEMA_ENABLED) + @Test + public void defaultDevice_recordAccess_persistToDisk() { + int uid = Process.myUid(); + String packageName = mContext.getOpPackageName(); + int op = AppOpsManager.OP_CAMERA; + String deviceId = VirtualDeviceManager.PERSISTENT_DEVICE_ID_DEFAULT; + long accessTime = System.currentTimeMillis(); + long duration = 60000L; + int uidState = UID_STATE_FOREGROUND; + int opFlags = OP_FLAGS_ALL_TRUSTED; + int attributionFlags = ATTRIBUTION_FLAG_ACCESSOR; + int attributionChainId = AppOpsManager.ATTRIBUTION_CHAIN_ID_NONE; + + mDiscreteRegistry.recordDiscreteAccess(uid, packageName, deviceId, op, null, opFlags, + uidState, accessTime, duration, attributionFlags, attributionChainId); + + // Verify in-memory object is correct + fetchDiscreteOpsAndValidate(uid, packageName, op, deviceId, null, accessTime, + duration, uidState, opFlags, attributionFlags, attributionChainId); + + // Write to disk and clear the in-memory object + mDiscreteRegistry.writeAndClearAccessHistory(); + + // Verify the storage file is created and then verify its content is correct + File[] files = FileUtils.listFilesOrEmpty(mMockDataDirectory); + assertThat(files.length).isEqualTo(1); + fetchDiscreteOpsAndValidate(uid, packageName, op, deviceId, null, accessTime, + duration, uidState, opFlags, attributionFlags, attributionChainId); + } + + @RequiresFlagsEnabled(Flags.FLAG_DEVICE_AWARE_APP_OP_NEW_SCHEMA_ENABLED) + @Test + public void externalDevice_recordAccess_persistToDisk() { + int uid = Process.myUid(); + String packageName = mContext.getOpPackageName(); + int op = AppOpsManager.OP_CAMERA; + String deviceId = "companion:1"; + long accessTime = System.currentTimeMillis(); + long duration = -1; + int uidState = UID_STATE_FOREGROUND_SERVICE; + int opFlags = OP_FLAG_SELF; + int attributionFlags = ATTRIBUTION_FLAG_RECEIVER; + int attributionChainId = 10; + + mDiscreteRegistry.recordDiscreteAccess(uid, packageName, deviceId, op, null, opFlags, + uidState, accessTime, duration, attributionFlags, attributionChainId); + + fetchDiscreteOpsAndValidate(uid, packageName, op, deviceId, null, accessTime, + duration, uidState, opFlags, attributionFlags, attributionChainId); + + mDiscreteRegistry.writeAndClearAccessHistory(); + + File[] files = FileUtils.listFilesOrEmpty(mMockDataDirectory); + assertThat(files.length).isEqualTo(1); + fetchDiscreteOpsAndValidate(uid, packageName, op, deviceId, null, accessTime, + duration, uidState, opFlags, attributionFlags, attributionChainId); + } + + private void fetchDiscreteOpsAndValidate(int expectedUid, String expectedPackageName, + int expectedOp, String expectedDeviceId, String expectedAttrTag, + long expectedAccessTime, long expectedAccessDuration, int expectedUidState, + int expectedOpFlags, int expectedAttrFlags, int expectedAttrChainId) { + DiscreteRegistry.DiscreteOps discreteOps = mDiscreteRegistry.getAllDiscreteOps(); + + assertThat(discreteOps.isEmpty()).isFalse(); + assertThat(discreteOps.mUids.size()).isEqualTo(1); + + DiscreteRegistry.DiscreteUidOps discreteUidOps = discreteOps.mUids.get(expectedUid); + assertThat(discreteUidOps.mPackages.size()).isEqualTo(1); + + DiscreteRegistry.DiscretePackageOps discretePackageOps = + discreteUidOps.mPackages.get(expectedPackageName); + assertThat(discretePackageOps.mPackageOps.size()).isEqualTo(1); + + DiscreteRegistry.DiscreteOp discreteOp = discretePackageOps.mPackageOps.get(expectedOp); + assertThat(discreteOp.mDeviceAttributedOps.size()).isEqualTo(1); + + DiscreteRegistry.DiscreteDeviceOp discreteDeviceOp = + discreteOp.mDeviceAttributedOps.get(expectedDeviceId); + assertThat(discreteDeviceOp.mAttributedOps.size()).isEqualTo(1); + + List<DiscreteRegistry.DiscreteOpEvent> discreteOpEvents = + discreteDeviceOp.mAttributedOps.get(expectedAttrTag); + assertThat(discreteOpEvents.size()).isEqualTo(1); + + DiscreteRegistry.DiscreteOpEvent discreteOpEvent = discreteOpEvents.get(0); + assertThat(discreteOpEvent.mNoteTime).isEqualTo(expectedAccessTime); + assertThat(discreteOpEvent.mNoteDuration).isEqualTo(expectedAccessDuration); + assertThat(discreteOpEvent.mUidState).isEqualTo(expectedUidState); + assertThat(discreteOpEvent.mOpFlag).isEqualTo(expectedOpFlags); + assertThat(discreteOpEvent.mAttributionFlags).isEqualTo(expectedAttrFlags); + assertThat(discreteOpEvent.mAttributionChainId).isEqualTo(expectedAttrChainId); + } +} diff --git a/services/tests/servicestests/src/com/android/server/audio/AudioDeviceInventoryTest.java b/services/tests/servicestests/src/com/android/server/audio/AudioDeviceInventoryTest.java new file mode 100644 index 000000000000..b5a538fa09f8 --- /dev/null +++ b/services/tests/servicestests/src/com/android/server/audio/AudioDeviceInventoryTest.java @@ -0,0 +1,144 @@ +/* + * Copyright 2024 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package com.android.server.audio; + +import static com.android.media.audio.Flags.asDeviceConnectionFailure; + +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertTrue; +import static org.mockito.Mockito.mock; +import static org.mockito.Mockito.spy; +import static org.mockito.Mockito.when; + +import android.Manifest; +import android.bluetooth.BluetoothAdapter; +import android.bluetooth.BluetoothDevice; +import android.bluetooth.BluetoothProfile; +import android.content.Context; +import android.media.AudioDeviceAttributes; +import android.media.AudioManager; +import android.media.AudioSystem; +import android.platform.test.annotations.Presubmit; +import android.util.Log; + +import androidx.test.ext.junit.runners.AndroidJUnit4; +import androidx.test.filters.MediumTest; +import androidx.test.platform.app.InstrumentationRegistry; + +import org.junit.After; +import org.junit.Before; +import org.junit.Test; +import org.junit.runner.RunWith; +import org.mockito.Mock; +import org.mockito.Spy; + +@MediumTest +@Presubmit +@RunWith(AndroidJUnit4.class) +public class AudioDeviceInventoryTest { + + private static final String TAG = "AudioDeviceInventoryTest"; + + @Mock private AudioService mMockAudioService; + private AudioDeviceInventory mDevInventory; + @Spy private AudioDeviceBroker mSpyAudioDeviceBroker; + @Spy private AudioSystemAdapter mSpyAudioSystem; + + private SystemServerAdapter mSystemServer; + + private BluetoothDevice mFakeBtDevice; + + @Before + public void setUp() throws Exception { + Context context = InstrumentationRegistry.getInstrumentation().getTargetContext(); + + mMockAudioService = mock(AudioService.class); + mSpyAudioSystem = spy(new NoOpAudioSystemAdapter()); + mDevInventory = new AudioDeviceInventory(mSpyAudioSystem); + mSystemServer = new NoOpSystemServerAdapter(); + mSpyAudioDeviceBroker = spy(new AudioDeviceBroker(context, mMockAudioService, mDevInventory, + mSystemServer, mSpyAudioSystem)); + mDevInventory.setDeviceBroker(mSpyAudioDeviceBroker); + + BluetoothAdapter adapter = BluetoothAdapter.getDefaultAdapter(); + mFakeBtDevice = adapter.getRemoteDevice("00:01:02:03:04:05"); + } + + @After + public void tearDown() throws Exception { } + + /** + * test that for DEVICE_OUT_BLUETOOTH_A2DP devices, when the device connects, it's only + * added to the connected devices when the connection through AudioSystem is successful + * @throws Exception on error + */ + @Test + public void testSetDeviceConnectionStateA2dp() throws Exception { + Log.i(TAG, "starting testSetDeviceConnectionStateA2dp"); + assertTrue("collection of connected devices not empty at start", + mDevInventory.getConnectedDevices().isEmpty()); + + final AudioDeviceAttributes ada = new AudioDeviceAttributes( + AudioSystem.DEVICE_OUT_BLUETOOTH_A2DP, mFakeBtDevice.getAddress()); + AudioDeviceBroker.BtDeviceInfo btInfo = + new AudioDeviceBroker.BtDeviceInfo(mFakeBtDevice, BluetoothProfile.A2DP, + BluetoothProfile.STATE_CONNECTED, AudioSystem.DEVICE_OUT_BLUETOOTH_A2DP, + AudioSystem.AUDIO_FORMAT_SBC); + + // test that no device is added when AudioSystem returns AUDIO_STATUS_ERROR + // when setDeviceConnectionState is called for the connection + // NOTE: for now this is only when flag asDeviceConnectionFailure is true + if (asDeviceConnectionFailure()) { + when(mSpyAudioSystem.setDeviceConnectionState(ada, AudioSystem.DEVICE_STATE_AVAILABLE, + AudioSystem.AUDIO_FORMAT_DEFAULT)) + .thenReturn(AudioSystem.AUDIO_STATUS_ERROR); + runWithBluetoothPrivilegedPermission( + () -> mDevInventory.onSetBtActiveDevice(/*btInfo*/ btInfo, + /*codec*/ AudioSystem.AUDIO_FORMAT_DEFAULT, AudioManager.STREAM_MUSIC)); + + assertEquals(0, mDevInventory.getConnectedDevices().size()); + } + + // test that the device is added when AudioSystem returns AUDIO_STATUS_OK + // when setDeviceConnectionState is called for the connection + when(mSpyAudioSystem.setDeviceConnectionState(ada, AudioSystem.DEVICE_STATE_AVAILABLE, + AudioSystem.AUDIO_FORMAT_DEFAULT)) + .thenReturn(AudioSystem.AUDIO_STATUS_OK); + runWithBluetoothPrivilegedPermission( + () -> mDevInventory.onSetBtActiveDevice(/*btInfo*/ btInfo, + /*codec*/ AudioSystem.AUDIO_FORMAT_DEFAULT, AudioManager.STREAM_MUSIC)); + assertEquals(1, mDevInventory.getConnectedDevices().size()); + } + + // TODO add test for hearing aid + + // TODO add test for BLE + + /** + * Executes a Runnable while holding the BLUETOOTH_PRIVILEGED permission + * @param toRunWithPermission the runnable to run with BT privileges + */ + private void runWithBluetoothPrivilegedPermission(Runnable toRunWithPermission) { + try { + InstrumentationRegistry.getInstrumentation().getUiAutomation() + .adoptShellPermissionIdentity(Manifest.permission.BLUETOOTH_PRIVILEGED); + toRunWithPermission.run(); + } finally { + InstrumentationRegistry.getInstrumentation().getUiAutomation() + .dropShellPermissionIdentity(); + } + } +} diff --git a/services/tests/servicestests/src/com/android/server/biometrics/sensors/BiometricSchedulerTest.java b/services/tests/servicestests/src/com/android/server/biometrics/sensors/BiometricSchedulerTest.java index 37895315557a..36a7b3dff28d 100644 --- a/services/tests/servicestests/src/com/android/server/biometrics/sensors/BiometricSchedulerTest.java +++ b/services/tests/servicestests/src/com/android/server/biometrics/sensors/BiometricSchedulerTest.java @@ -1296,6 +1296,11 @@ public class BiometricSchedulerTest { mFingerprints.add((Fingerprint) identifier); } + @Override + protected int getModality() { + return 0; + } + public List<Fingerprint> getFingerprints() { return mFingerprints; } diff --git a/services/tests/servicestests/src/com/android/server/biometrics/sensors/fingerprint/aidl/FingerprintInternalCleanupClientTest.java b/services/tests/servicestests/src/com/android/server/biometrics/sensors/fingerprint/aidl/FingerprintInternalCleanupClientTest.java index c9482ceb00f5..a34e7965ccee 100644 --- a/services/tests/servicestests/src/com/android/server/biometrics/sensors/fingerprint/aidl/FingerprintInternalCleanupClientTest.java +++ b/services/tests/servicestests/src/com/android/server/biometrics/sensors/fingerprint/aidl/FingerprintInternalCleanupClientTest.java @@ -19,6 +19,7 @@ package com.android.server.biometrics.sensors.fingerprint.aidl; import static com.google.common.truth.Truth.assertThat; import static org.mockito.Mockito.any; +import static org.mockito.Mockito.doReturn; import static org.mockito.Mockito.eq; import static org.mockito.Mockito.never; import static org.mockito.Mockito.times; @@ -30,12 +31,16 @@ import android.hardware.biometrics.fingerprint.ISession; import android.hardware.fingerprint.Fingerprint; import android.os.RemoteException; import android.platform.test.annotations.Presubmit; +import android.platform.test.annotations.RequiresFlagsEnabled; +import android.platform.test.flag.junit.CheckFlagsRule; +import android.platform.test.flag.junit.DeviceFlagsValueProvider; import android.testing.TestableContext; import androidx.annotation.NonNull; import androidx.test.filters.SmallTest; import androidx.test.platform.app.InstrumentationRegistry; +import com.android.server.biometrics.Flags; import com.android.server.biometrics.log.BiometricContext; import com.android.server.biometrics.log.BiometricLogger; import com.android.server.biometrics.sensors.ClientMonitorCallback; @@ -69,6 +74,10 @@ public class FingerprintInternalCleanupClientTest { public final TestableContext mContext = new TestableContext( InstrumentationRegistry.getInstrumentation().getTargetContext(), null); + @Rule + public final CheckFlagsRule mCheckFlagsRule = + DeviceFlagsValueProvider.createCheckFlagsRule(); + @Mock ISession mSession; @Mock @@ -168,6 +177,21 @@ public class FingerprintInternalCleanupClientTest { assertThat(mClient.getUnknownHALTemplates()).isEmpty(); } + @Test + @RequiresFlagsEnabled(Flags.FLAG_NOTIFY_FINGERPRINT_LOE) + public void invalidBiometricUserState() throws Exception { + mClient = createClient(); + + final List<Fingerprint> list = new ArrayList<>(); + doReturn(true).when(mFingerprintUtils) + .hasValidBiometricUserState(mContext, 2); + doReturn(list).when(mFingerprintUtils).getBiometricsForUser(mContext, 2); + + mClient.start(mCallback); + mClient.onEnumerationResult(null, 0); + verify(mFingerprintUtils).deleteStateForUser(2); + } + protected FingerprintInternalCleanupClient createClient() { final Map<Integer, Long> authenticatorIds = new HashMap<>(); return new FingerprintInternalCleanupClient(mContext, () -> mAidlSession, 2 /* userId */, diff --git a/services/tests/servicestests/src/com/android/server/hdmi/HdmiCecLocalDeviceTvTest.java b/services/tests/servicestests/src/com/android/server/hdmi/HdmiCecLocalDeviceTvTest.java index 87b52e6194ce..f98bbf9cce4c 100644 --- a/services/tests/servicestests/src/com/android/server/hdmi/HdmiCecLocalDeviceTvTest.java +++ b/services/tests/servicestests/src/com/android/server/hdmi/HdmiCecLocalDeviceTvTest.java @@ -28,6 +28,7 @@ import static com.android.server.hdmi.HdmiControlService.INITIATED_BY_ENABLE_CEC import static com.android.server.hdmi.HdmiControlService.INITIATED_BY_WAKE_UP_MESSAGE; import static com.android.server.hdmi.HdmiControlService.STANDBY_SCREEN_OFF; import static com.android.server.hdmi.HdmiControlService.WAKE_UP_SCREEN_ON; +import static com.android.server.hdmi.RequestActiveSourceAction.TIMEOUT_WAIT_FOR_LAUNCHERX_API_CALL_MS; import static com.google.common.truth.Truth.assertThat; @@ -1792,7 +1793,7 @@ public class HdmiCecLocalDeviceTvTest { mTestLooper.dispatchAll(); // Skip the LauncherX API timeout. - mTestLooper.moveTimeForward(HdmiConfig.TIMEOUT_MS * 2); + mTestLooper.moveTimeForward(TIMEOUT_WAIT_FOR_LAUNCHERX_API_CALL_MS); mTestLooper.dispatchAll(); assertThat(mNativeWrapper.getResultMessages()).contains(requestActiveSource); @@ -1825,7 +1826,7 @@ public class HdmiCecLocalDeviceTvTest { mTestLooper.dispatchAll(); // Skip the LauncherX API timeout. - mTestLooper.moveTimeForward(HdmiConfig.TIMEOUT_MS * 2); + mTestLooper.moveTimeForward(TIMEOUT_WAIT_FOR_LAUNCHERX_API_CALL_MS); mTestLooper.dispatchAll(); assertThat(mNativeWrapper.getResultMessages()).contains(requestActiveSource); @@ -1861,7 +1862,7 @@ public class HdmiCecLocalDeviceTvTest { mTestLooper.dispatchAll(); // Skip the LauncherX API timeout. - mTestLooper.moveTimeForward(HdmiConfig.TIMEOUT_MS * 2); + mTestLooper.moveTimeForward(TIMEOUT_WAIT_FOR_LAUNCHERX_API_CALL_MS); mTestLooper.dispatchAll(); assertThat(mNativeWrapper.getResultMessages()).contains(requestActiveSource); @@ -1904,7 +1905,7 @@ public class HdmiCecLocalDeviceTvTest { mTestLooper.dispatchAll(); // Skip the LauncherX API timeout. - mTestLooper.moveTimeForward(HdmiConfig.TIMEOUT_MS * 2); + mTestLooper.moveTimeForward(TIMEOUT_WAIT_FOR_LAUNCHERX_API_CALL_MS); mTestLooper.dispatchAll(); assertThat(mNativeWrapper.getResultMessages()).contains(requestActiveSource); @@ -1941,7 +1942,7 @@ public class HdmiCecLocalDeviceTvTest { mHdmiControlService.sendCecCommand(setStreamPathFromTv); // Skip the LauncherX API timeout. - mTestLooper.moveTimeForward(HdmiConfig.TIMEOUT_MS * 2); + mTestLooper.moveTimeForward(TIMEOUT_WAIT_FOR_LAUNCHERX_API_CALL_MS); mTestLooper.dispatchAll(); assertThat(mNativeWrapper.getResultMessages()).doesNotContain(requestActiveSource); diff --git a/services/tests/servicestests/src/com/android/server/hdmi/HdmiCecNetworkTest.java b/services/tests/servicestests/src/com/android/server/hdmi/HdmiCecNetworkTest.java index 599a3b86e1af..4f7f381a33d6 100644 --- a/services/tests/servicestests/src/com/android/server/hdmi/HdmiCecNetworkTest.java +++ b/services/tests/servicestests/src/com/android/server/hdmi/HdmiCecNetworkTest.java @@ -270,6 +270,36 @@ public class HdmiCecNetworkTest { } @Test + public void cecDevices_tracking_event_update_device() { + int logicalAddress = Constants.ADDR_PLAYBACK_1; + int initialPhysicalAddress = 0x1000; + int type = HdmiDeviceInfo.DEVICE_PLAYBACK; + String osdName = "Test Device"; + + mHdmiCecNetwork.handleCecMessage( + HdmiCecMessageBuilder.buildReportPhysicalAddressCommand(logicalAddress, + initialPhysicalAddress, type)); + // Change OSD to make the info different + mHdmiCecNetwork.handleCecMessage( + HdmiCecMessageBuilder.buildSetOsdNameCommand(logicalAddress, + Constants.ADDR_BROADCAST, osdName)); + synchronized (mHdmiCecNetwork.mLock) { + assertThat(mHdmiCecNetwork.getSafeCecDevicesLocked()).hasSize(1); + } + + HdmiDeviceInfo cecDeviceInfo = mHdmiCecNetwork.getCecDeviceInfo(logicalAddress); + assertThat(cecDeviceInfo.getLogicalAddress()).isEqualTo(logicalAddress); + assertThat(cecDeviceInfo.getPhysicalAddress()).isEqualTo(initialPhysicalAddress); + assertThat(cecDeviceInfo.getDeviceType()).isEqualTo(type); + + // ADD for physical address first detected + // UPDATE for updating device with new OSD name + assertThat(mDeviceEventListenerStatuses).containsExactly( + HdmiControlManager.DEVICE_EVENT_ADD_DEVICE, + HdmiControlManager.DEVICE_EVENT_UPDATE_DEVICE); + } + + @Test public void cecDevices_tracking_updateDeviceInfo_sameDoesntNotify() { int logicalAddress = Constants.ADDR_PLAYBACK_1; int physicalAddress = 0x1000; diff --git a/services/tests/servicestests/src/com/android/server/power/hint/TEST_MAPPING b/services/tests/servicestests/src/com/android/server/power/hint/TEST_MAPPING deleted file mode 100644 index 874eec75b229..000000000000 --- a/services/tests/servicestests/src/com/android/server/power/hint/TEST_MAPPING +++ /dev/null @@ -1,15 +0,0 @@ -{ - "presubmit": [ - { - "name": "FrameworksServicesTests", - "options": [ - { - "include-filter": "com.android.server.power.hint" - }, - { - "exclude-annotation": "androidx.test.filters.FlakyTest" - } - ] - } - ] -} diff --git a/services/tests/timetests/src/com/android/server/timezonedetector/location/ZoneInfoDbTimeZoneProviderEventPreProcessorTest.java b/services/tests/timetests/src/com/android/server/timezonedetector/location/ZoneInfoDbTimeZoneProviderEventPreProcessorTest.java index f3440f7c9d1c..ea3b409e5929 100644 --- a/services/tests/timetests/src/com/android/server/timezonedetector/location/ZoneInfoDbTimeZoneProviderEventPreProcessorTest.java +++ b/services/tests/timetests/src/com/android/server/timezonedetector/location/ZoneInfoDbTimeZoneProviderEventPreProcessorTest.java @@ -39,13 +39,23 @@ public class ZoneInfoDbTimeZoneProviderEventPreProcessorTest { private static final long ARBITRARY_TIME_MILLIS = 11223344; + private final List<String> mNonExistingTimeZones = Arrays.asList( + "SystemV/HST10", "Atlantic/Atlantis", "EUROPE/LONDON", "Etc/GMT-5:30"); private final ZoneInfoDbTimeZoneProviderEventPreProcessor mPreProcessor = new ZoneInfoDbTimeZoneProviderEventPreProcessor(); + private static final TimeZoneProviderStatus ARBITRARY_TIME_ZONE_PROVIDER_STATUS = + new TimeZoneProviderStatus.Builder() + .setConnectivityDependencyStatus(DEPENDENCY_STATUS_OK) + .setLocationDetectionDependencyStatus(DEPENDENCY_STATUS_OK) + .setTimeZoneResolutionOperationStatus(OPERATION_STATUS_OK) + .build(); + @Test public void timeZoneIdsFromZoneInfoDbAreValid() { for (String timeZone : TimeZone.getAvailableIDs()) { - TimeZoneProviderEvent event = timeZoneProviderEvent(timeZone); + TimeZoneProviderEvent event = timeZoneProviderEvent(timeZone, + ARBITRARY_TIME_ZONE_PROVIDER_STATUS); assertWithMessage("Time zone %s should be supported", timeZone) .that(mPreProcessor.preProcess(event)).isEqualTo(event); } @@ -53,11 +63,9 @@ public class ZoneInfoDbTimeZoneProviderEventPreProcessorTest { @Test public void eventWithNonExistingZones_areMappedToUncertainEvent() { - List<String> nonExistingTimeZones = Arrays.asList( - "SystemV/HST10", "Atlantic/Atlantis", "EUROPE/LONDON", "Etc/GMT-5:30"); - - for (String timeZone : nonExistingTimeZones) { - TimeZoneProviderEvent event = timeZoneProviderEvent(timeZone); + for (String timeZone : mNonExistingTimeZones) { + TimeZoneProviderEvent event = timeZoneProviderEvent(timeZone, + ARBITRARY_TIME_ZONE_PROVIDER_STATUS); TimeZoneProviderStatus expectedProviderStatus = new TimeZoneProviderStatus.Builder(event.getTimeZoneProviderStatus()) @@ -73,14 +81,31 @@ public class ZoneInfoDbTimeZoneProviderEventPreProcessorTest { } } - private static TimeZoneProviderEvent timeZoneProviderEvent(String... timeZoneIds) { - TimeZoneProviderStatus providerStatus = new TimeZoneProviderStatus.Builder() - .setLocationDetectionDependencyStatus(DEPENDENCY_STATUS_OK) - .setConnectivityDependencyStatus(DEPENDENCY_STATUS_OK) - .setTimeZoneResolutionOperationStatus(OPERATION_STATUS_OK) - .build(); + @Test + public void eventWithNullProviderStatus_areMappedToUncertainEvent() { + for (String timeZone : mNonExistingTimeZones) { + TimeZoneProviderEvent eventWithNullStatus = timeZoneProviderEvent(timeZone, + /* providerStatus= */ null); + + TimeZoneProviderStatus expectedProviderStatus = + new TimeZoneProviderStatus.Builder() + .setTimeZoneResolutionOperationStatus(OPERATION_STATUS_FAILED) + .build(); + + TimeZoneProviderEvent expectedResultEvent = + TimeZoneProviderEvent.createUncertainEvent( + eventWithNullStatus.getCreationElapsedMillis(), + expectedProviderStatus); + assertWithMessage(timeZone + " with null time zone provider status") + .that(mPreProcessor.preProcess(eventWithNullStatus)) + .isEqualTo(expectedResultEvent); + } + } + + private static TimeZoneProviderEvent timeZoneProviderEvent(String timeZoneId, + TimeZoneProviderStatus providerStatus) { TimeZoneProviderSuggestion suggestion = new TimeZoneProviderSuggestion.Builder() - .setTimeZoneIds(Arrays.asList(timeZoneIds)) + .setTimeZoneIds(Arrays.asList(timeZoneId)) .setElapsedRealtimeMillis(ARBITRARY_TIME_MILLIS) .build(); return TimeZoneProviderEvent.createSuggestionEvent( diff --git a/services/tests/uiservicestests/src/com/android/server/notification/ManagedServicesTest.java b/services/tests/uiservicestests/src/com/android/server/notification/ManagedServicesTest.java index e5c42082ab97..fb82b872cf80 100644 --- a/services/tests/uiservicestests/src/com/android/server/notification/ManagedServicesTest.java +++ b/services/tests/uiservicestests/src/com/android/server/notification/ManagedServicesTest.java @@ -888,7 +888,7 @@ public class ManagedServicesTest extends UiServiceTestCase { return true; }); - mockServiceInfoWithMetaData(List.of(cn), service, new ArrayMap<>()); + mockServiceInfoWithMetaData(List.of(cn), service, pm, new ArrayMap<>()); service.addApprovedList("a", 0, true); service.reregisterService(cn, 0); @@ -919,7 +919,7 @@ public class ManagedServicesTest extends UiServiceTestCase { return true; }); - mockServiceInfoWithMetaData(List.of(cn), service, new ArrayMap<>()); + mockServiceInfoWithMetaData(List.of(cn), service, pm, new ArrayMap<>()); service.addApprovedList("a", 0, false); service.reregisterService(cn, 0); @@ -950,7 +950,7 @@ public class ManagedServicesTest extends UiServiceTestCase { return true; }); - mockServiceInfoWithMetaData(List.of(cn), service, new ArrayMap<>()); + mockServiceInfoWithMetaData(List.of(cn), service, pm, new ArrayMap<>()); service.addApprovedList("a/a", 0, true); service.reregisterService(cn, 0); @@ -981,7 +981,7 @@ public class ManagedServicesTest extends UiServiceTestCase { return true; }); - mockServiceInfoWithMetaData(List.of(cn), service, new ArrayMap<>()); + mockServiceInfoWithMetaData(List.of(cn), service, pm, new ArrayMap<>()); service.addApprovedList("a/a", 0, false); service.reregisterService(cn, 0); @@ -1211,6 +1211,64 @@ public class ManagedServicesTest extends UiServiceTestCase { } @Test + public void testUpgradeAppNoIntentFilterNoRebind() throws Exception { + Context context = spy(getContext()); + doReturn(true).when(context).bindServiceAsUser(any(), any(), anyInt(), any()); + + ManagedServices service = new TestManagedServices(context, mLock, mUserProfiles, + mIpm, APPROVAL_BY_COMPONENT); + + List<String> packages = new ArrayList<>(); + packages.add("package"); + addExpectedServices(service, packages, 0); + + final ComponentName unapprovedComponent = ComponentName.unflattenFromString("package/C1"); + final ComponentName approvedComponent = ComponentName.unflattenFromString("package/C2"); + + // Both components are approved initially + mExpectedPrimaryComponentNames.clear(); + mExpectedPrimaryPackages.clear(); + mExpectedPrimaryComponentNames.put(0, "package/C1:package/C2"); + mExpectedSecondaryComponentNames.clear(); + mExpectedSecondaryPackages.clear(); + + loadXml(service); + + //Component package/C1 loses serviceInterface intent filter + ManagedServices.Config config = service.getConfig(); + when(mPm.queryIntentServicesAsUser(any(), anyInt(), anyInt())). + thenAnswer(new Answer<List<ResolveInfo>>() { + @Override + public List<ResolveInfo> answer(InvocationOnMock invocationOnMock) + throws Throwable { + Object[] args = invocationOnMock.getArguments(); + Intent invocationIntent = (Intent) args[0]; + if (invocationIntent != null) { + if (invocationIntent.getAction().equals(config.serviceInterface) + && packages.contains(invocationIntent.getPackage())) { + List<ResolveInfo> dummyServices = new ArrayList<>(); + ResolveInfo resolveInfo = new ResolveInfo(); + ServiceInfo serviceInfo = new ServiceInfo(); + serviceInfo.packageName = invocationIntent.getPackage(); + serviceInfo.name = approvedComponent.getClassName(); + serviceInfo.permission = service.getConfig().bindPermission; + resolveInfo.serviceInfo = serviceInfo; + dummyServices.add(resolveInfo); + return dummyServices; + } + } + return new ArrayList<>(); + } + }); + + // Trigger package update + service.onPackagesChanged(false, new String[]{"package"}, new int[]{0}); + + assertFalse(service.isComponentEnabledForCurrentProfiles(unapprovedComponent)); + assertTrue(service.isComponentEnabledForCurrentProfiles(approvedComponent)); + } + + @Test public void testSetPackageOrComponentEnabled() throws Exception { for (int approvalLevel : new int[] {APPROVAL_BY_COMPONENT, APPROVAL_BY_PACKAGE}) { ManagedServices service = new TestManagedServices(getContext(), mLock, mUserProfiles, @@ -1915,7 +1973,7 @@ public class ManagedServicesTest extends UiServiceTestCase { metaDataAutobindAllow.putBoolean(META_DATA_DEFAULT_AUTOBIND, true); metaDatas.put(cn_allowed, metaDataAutobindAllow); - mockServiceInfoWithMetaData(componentNames, service, metaDatas); + mockServiceInfoWithMetaData(componentNames, service, pm, metaDatas); service.addApprovedList(cn_allowed.flattenToString(), 0, true); service.addApprovedList(cn_disallowed.flattenToString(), 0, true); @@ -1960,7 +2018,7 @@ public class ManagedServicesTest extends UiServiceTestCase { metaDataAutobindDisallow.putBoolean(META_DATA_DEFAULT_AUTOBIND, false); metaDatas.put(cn_disallowed, metaDataAutobindDisallow); - mockServiceInfoWithMetaData(componentNames, service, metaDatas); + mockServiceInfoWithMetaData(componentNames, service, pm, metaDatas); service.addApprovedList(cn_disallowed.flattenToString(), 0, true); @@ -1999,7 +2057,7 @@ public class ManagedServicesTest extends UiServiceTestCase { metaDataAutobindDisallow.putBoolean(META_DATA_DEFAULT_AUTOBIND, false); metaDatas.put(cn_disallowed, metaDataAutobindDisallow); - mockServiceInfoWithMetaData(componentNames, service, metaDatas); + mockServiceInfoWithMetaData(componentNames, service, pm, metaDatas); service.addApprovedList(cn_disallowed.flattenToString(), 0, true); @@ -2070,8 +2128,8 @@ public class ManagedServicesTest extends UiServiceTestCase { } private void mockServiceInfoWithMetaData(List<ComponentName> componentNames, - ManagedServices service, ArrayMap<ComponentName, Bundle> metaDatas) - throws RemoteException { + ManagedServices service, PackageManager packageManager, + ArrayMap<ComponentName, Bundle> metaDatas) throws RemoteException { when(mIpm.getServiceInfo(any(), anyLong(), anyInt())).thenAnswer( (Answer<ServiceInfo>) invocation -> { ComponentName invocationCn = invocation.getArgument(0); @@ -2086,6 +2144,39 @@ public class ManagedServicesTest extends UiServiceTestCase { return null; } ); + + // add components to queryIntentServicesAsUser response + final List<String> packages = new ArrayList<>(); + for (ComponentName cn: componentNames) { + packages.add(cn.getPackageName()); + } + ManagedServices.Config config = service.getConfig(); + when(packageManager.queryIntentServicesAsUser(any(), anyInt(), anyInt())). + thenAnswer(new Answer<List<ResolveInfo>>() { + @Override + public List<ResolveInfo> answer(InvocationOnMock invocationOnMock) + throws Throwable { + Object[] args = invocationOnMock.getArguments(); + Intent invocationIntent = (Intent) args[0]; + if (invocationIntent != null) { + if (invocationIntent.getAction().equals(config.serviceInterface) + && packages.contains(invocationIntent.getPackage())) { + List<ResolveInfo> dummyServices = new ArrayList<>(); + for (ComponentName cn: componentNames) { + ResolveInfo resolveInfo = new ResolveInfo(); + ServiceInfo serviceInfo = new ServiceInfo(); + serviceInfo.packageName = invocationIntent.getPackage(); + serviceInfo.name = cn.getClassName(); + serviceInfo.permission = service.getConfig().bindPermission; + resolveInfo.serviceInfo = serviceInfo; + dummyServices.add(resolveInfo); + } + return dummyServices; + } + } + return new ArrayList<>(); + } + }); } private void resetComponentsAndPackages() { diff --git a/services/tests/uiservicestests/src/com/android/server/notification/NotificationManagerServiceTest.java b/services/tests/uiservicestests/src/com/android/server/notification/NotificationManagerServiceTest.java index c1f5a01a8c47..1b999e49d21b 100644 --- a/services/tests/uiservicestests/src/com/android/server/notification/NotificationManagerServiceTest.java +++ b/services/tests/uiservicestests/src/com/android/server/notification/NotificationManagerServiceTest.java @@ -3105,6 +3105,29 @@ public class NotificationManagerServiceTest extends UiServiceTestCase { } @Test + @EnableFlags(android.app.Flags.FLAG_LIFETIME_EXTENSION_REFACTOR) + public void testLifetimeExtendedCancelledOnClick() throws Exception { + // Adds a lifetime extended notification. + final NotificationRecord notif = generateNotificationRecord(mTestNotificationChannel, 1, + null, false); + notif.getSbn().getNotification().flags = + Notification.FLAG_LIFETIME_EXTENDED_BY_DIRECT_REPLY; + mService.addNotification(notif); + // Verify that the notification is posted and active. + assertThat(mBinderService.getActiveNotifications(mPkg).length).isEqualTo(1); + + // Click the notification. + final NotificationVisibility nv = NotificationVisibility.obtain(notif.getKey(), 1, 2, true); + mService.mNotificationDelegate.onNotificationClick(mUid, Binder.getCallingPid(), + notif.getKey(), nv); + waitForIdle(); + + // The notification has been cancelled. + StatusBarNotification[] notifs = mBinderService.getActiveNotifications(mPkg); + assertThat(notifs.length).isEqualTo(0); + } + + @Test public void testCancelNotificationWithTag_fromApp_cannotCancelFgsChild() throws Exception { when(mAmi.applyForegroundServiceNotification( diff --git a/services/tests/vibrator/src/com/android/server/vibrator/HapticFeedbackVibrationProviderTest.java b/services/tests/vibrator/src/com/android/server/vibrator/HapticFeedbackVibrationProviderTest.java index 901c0361092f..4f7593184d83 100644 --- a/services/tests/vibrator/src/com/android/server/vibrator/HapticFeedbackVibrationProviderTest.java +++ b/services/tests/vibrator/src/com/android/server/vibrator/HapticFeedbackVibrationProviderTest.java @@ -20,7 +20,7 @@ import static android.os.VibrationAttributes.CATEGORY_KEYBOARD; import static android.os.VibrationAttributes.CATEGORY_UNKNOWN; import static android.os.VibrationAttributes.FLAG_BYPASS_INTERRUPTION_POLICY; import static android.os.VibrationAttributes.FLAG_BYPASS_USER_VIBRATION_INTENSITY_OFF; -import static android.os.VibrationAttributes.FLAG_BYPASS_USER_VIBRATION_INTENSITY_SCALE; +import static android.os.VibrationAttributes.USAGE_IME_FEEDBACK; import static android.os.VibrationAttributes.USAGE_TOUCH; import static android.os.VibrationEffect.Composition.PRIMITIVE_CLICK; import static android.os.VibrationEffect.Composition.PRIMITIVE_TICK; @@ -346,7 +346,7 @@ public class HapticFeedbackVibrationProviderTest { } @Test - public void testVibrationAttribute_keyboardCategoryOff_isIme_notUseKeyboardCategory() { + public void testVibrationAttribute_keyboardCategoryOff_isIme_useTouchUsage() { mSetFlagsRule.disableFlags(Flags.FLAG_KEYBOARD_CATEGORY_ENABLED); HapticFeedbackVibrationProvider hapticProvider = createProviderWithDefaultCustomizations(); @@ -362,7 +362,7 @@ public class HapticFeedbackVibrationProviderTest { } @Test - public void testVibrationAttribute_keyboardCategoryOn_notIme_notUseKeyboardCategory() { + public void testVibrationAttribute_keyboardCategoryOn_notIme_useTouchUsage() { mSetFlagsRule.enableFlags(Flags.FLAG_KEYBOARD_CATEGORY_ENABLED); HapticFeedbackVibrationProvider hapticProvider = createProviderWithDefaultCustomizations(); @@ -377,7 +377,7 @@ public class HapticFeedbackVibrationProviderTest { } @Test - public void testVibrationAttribute_keyboardCategoryOn_isIme_useKeyboardCategory() { + public void testVibrationAttribute_keyboardCategoryOn_isIme_useImeFeedbackUsage() { mSetFlagsRule.enableFlags(Flags.FLAG_KEYBOARD_CATEGORY_ENABLED); HapticFeedbackVibrationProvider hapticProvider = createProviderWithDefaultCustomizations(); @@ -385,64 +385,14 @@ public class HapticFeedbackVibrationProviderTest { VibrationAttributes attrs = hapticProvider.getVibrationAttributesForHapticFeedback( effectId, /* flags */ 0, HapticFeedbackConstants.PRIVATE_FLAG_APPLY_INPUT_METHOD_SETTINGS); - assertWithMessage("Expected USAGE_TOUCH for effect " + effectId) - .that(attrs.getUsage()).isEqualTo(USAGE_TOUCH); + assertWithMessage("Expected USAGE_IME_FEEDBACK for effect " + effectId) + .that(attrs.getUsage()).isEqualTo(USAGE_IME_FEEDBACK); assertWithMessage("Expected CATEGORY_KEYBOARD for effect " + effectId) .that(attrs.getCategory()).isEqualTo(CATEGORY_KEYBOARD); } } @Test - public void testVibrationAttribute_noFixAmplitude_notBypassIntensityScale() { - mSetFlagsRule.enableFlags(Flags.FLAG_KEYBOARD_CATEGORY_ENABLED); - mockVibratorPrimitiveSupport(PRIMITIVE_CLICK, PRIMITIVE_TICK); - mockKeyboardVibrationFixedAmplitude(-1); - HapticFeedbackVibrationProvider hapticProvider = createProviderWithDefaultCustomizations(); - - for (int effectId : KEYBOARD_FEEDBACK_CONSTANTS) { - VibrationAttributes attrs = hapticProvider.getVibrationAttributesForHapticFeedback( - effectId, /* flags */ 0, - HapticFeedbackConstants.PRIVATE_FLAG_APPLY_INPUT_METHOD_SETTINGS); - assertWithMessage("Expected no FLAG_BYPASS_USER_VIBRATION_INTENSITY_SCALE for effect " - + effectId) - .that(attrs.isFlagSet(FLAG_BYPASS_USER_VIBRATION_INTENSITY_SCALE)).isFalse(); - } - } - - @Test - public void testVibrationAttribute_notIme_notBypassIntensityScale() { - mSetFlagsRule.enableFlags(Flags.FLAG_KEYBOARD_CATEGORY_ENABLED); - mockVibratorPrimitiveSupport(PRIMITIVE_CLICK, PRIMITIVE_TICK); - mockKeyboardVibrationFixedAmplitude(KEYBOARD_VIBRATION_FIXED_AMPLITUDE); - HapticFeedbackVibrationProvider hapticProvider = createProviderWithDefaultCustomizations(); - - for (int effectId : KEYBOARD_FEEDBACK_CONSTANTS) { - VibrationAttributes attrs = hapticProvider.getVibrationAttributesForHapticFeedback( - effectId, /* flags */ 0, /* privFlags */ 0); - assertWithMessage("Expected no FLAG_BYPASS_USER_VIBRATION_INTENSITY_SCALE for effect " - + effectId) - .that(attrs.isFlagSet(FLAG_BYPASS_USER_VIBRATION_INTENSITY_SCALE)).isFalse(); - } - } - - @Test - public void testVibrationAttribute_fixAmplitude_isIme_bypassIntensityScale() { - mSetFlagsRule.enableFlags(Flags.FLAG_KEYBOARD_CATEGORY_ENABLED); - mockVibratorPrimitiveSupport(PRIMITIVE_CLICK, PRIMITIVE_TICK); - mockKeyboardVibrationFixedAmplitude(KEYBOARD_VIBRATION_FIXED_AMPLITUDE); - HapticFeedbackVibrationProvider hapticProvider = createProviderWithDefaultCustomizations(); - - for (int effectId : KEYBOARD_FEEDBACK_CONSTANTS) { - VibrationAttributes attrs = hapticProvider.getVibrationAttributesForHapticFeedback( - effectId, /* flags */ 0, - HapticFeedbackConstants.PRIVATE_FLAG_APPLY_INPUT_METHOD_SETTINGS); - assertWithMessage("Expected FLAG_BYPASS_USER_VIBRATION_INTENSITY_SCALE for effect " - + effectId) - .that(attrs.isFlagSet(FLAG_BYPASS_USER_VIBRATION_INTENSITY_SCALE)).isTrue(); - } - } - - @Test public void testIsRestricted_biometricConstants_returnsTrue() { HapticFeedbackVibrationProvider hapticProvider = createProviderWithDefaultCustomizations(); diff --git a/services/tests/vibrator/src/com/android/server/vibrator/VibrationSettingsTest.java b/services/tests/vibrator/src/com/android/server/vibrator/VibrationSettingsTest.java index 60d8964267f1..8d4a6aa5ba29 100644 --- a/services/tests/vibrator/src/com/android/server/vibrator/VibrationSettingsTest.java +++ b/services/tests/vibrator/src/com/android/server/vibrator/VibrationSettingsTest.java @@ -23,6 +23,7 @@ import static android.os.VibrationAttributes.USAGE_ACCESSIBILITY; import static android.os.VibrationAttributes.USAGE_ALARM; import static android.os.VibrationAttributes.USAGE_COMMUNICATION_REQUEST; import static android.os.VibrationAttributes.USAGE_HARDWARE_FEEDBACK; +import static android.os.VibrationAttributes.USAGE_IME_FEEDBACK; import static android.os.VibrationAttributes.USAGE_MEDIA; import static android.os.VibrationAttributes.USAGE_NOTIFICATION; import static android.os.VibrationAttributes.USAGE_PHYSICAL_EMULATION; @@ -893,6 +894,22 @@ public class VibrationSettingsTest { } @Test + public void getCurrentIntensity_ImeFeedbackValueReflectsToKeyboardVibrationSettings() { + setDefaultIntensity(USAGE_IME_FEEDBACK, VIBRATION_INTENSITY_MEDIUM); + setDefaultIntensity(USAGE_TOUCH, VIBRATION_INTENSITY_HIGH); + + setKeyboardVibrationSettingsSupported(false); + mVibrationSettings.update(); + assertEquals(VIBRATION_INTENSITY_HIGH, + mVibrationSettings.getCurrentIntensity(USAGE_IME_FEEDBACK)); + + setKeyboardVibrationSettingsSupported(true); + mVibrationSettings.update(); + assertEquals(VIBRATION_INTENSITY_MEDIUM, + mVibrationSettings.getCurrentIntensity(USAGE_IME_FEEDBACK)); + } + + @Test public void getFallbackEffect_returnsEffectsFromSettings() { assertNotNull(mVibrationSettings.getFallbackEffect(VibrationEffect.EFFECT_TICK)); assertNotNull(mVibrationSettings.getFallbackEffect(VibrationEffect.EFFECT_TEXTURE_TICK)); diff --git a/services/tests/vibrator/src/com/android/server/vibrator/VibratorControlServiceTest.java b/services/tests/vibrator/src/com/android/server/vibrator/VibratorControlServiceTest.java index 8ca862390a65..c496bbb82630 100644 --- a/services/tests/vibrator/src/com/android/server/vibrator/VibratorControlServiceTest.java +++ b/services/tests/vibrator/src/com/android/server/vibrator/VibratorControlServiceTest.java @@ -45,6 +45,11 @@ import android.os.Handler; import android.os.IBinder; import android.os.Process; import android.os.test.TestLooper; +import android.os.vibrator.Flags; +import android.platform.test.annotations.RequiresFlagsDisabled; +import android.platform.test.annotations.RequiresFlagsEnabled; +import android.platform.test.flag.junit.CheckFlagsRule; +import android.platform.test.flag.junit.DeviceFlagsValueProvider; import android.util.SparseArray; import androidx.test.InstrumentationRegistry; @@ -63,7 +68,6 @@ import org.mockito.junit.MockitoRule; import java.util.Arrays; import java.util.List; import java.util.concurrent.CompletableFuture; -import java.util.concurrent.TimeUnit; public class VibratorControlServiceTest { @@ -71,6 +75,8 @@ public class VibratorControlServiceTest { @Rule public MockitoRule rule = MockitoJUnit.rule(); + @Rule + public final CheckFlagsRule mCheckFlagsRule = DeviceFlagsValueProvider.createCheckFlagsRule(); @Mock private VibrationScaler mMockVibrationScaler; @Mock private PackageManagerInternal mPackageManagerInternalMock; @@ -98,6 +104,7 @@ public class VibratorControlServiceTest { mVibratorControlService = new VibratorControlService( InstrumentationRegistry.getContext(), new VibratorControllerHolder(), mMockVibrationScaler, mVibrationSettings, mStatsLoggerMock, mLock); + mFakeVibratorController.setVibratorControlService(mVibratorControlService); } @Test @@ -280,10 +287,10 @@ public class VibratorControlServiceTest { CompletableFuture<Void> future = mVibratorControlService.triggerVibrationParamsRequest(UID, USAGE_RINGTONE, timeoutInMillis); - try { - future.orTimeout(timeoutInMillis, TimeUnit.MILLISECONDS).get(); - } catch (Throwable ignored) { - } + mTestLooper.dispatchAll(); + + assertThat(future).isNotNull(); + assertThat(future.isDone()).isTrue(); assertThat(mFakeVibratorController.didRequestVibrationParams).isTrue(); assertThat(mFakeVibratorController.requestVibrationType).isEqualTo( ScaleParam.TYPE_RINGTONE); @@ -315,6 +322,46 @@ public class VibratorControlServiceTest { } } + @Test + @RequiresFlagsEnabled(Flags.FLAG_THROTTLE_VIBRATION_PARAMS_REQUESTS) + public void testRequestVibrationParams_withOngoingRequestAndSameUsage_returnOngoingFuture() { + int timeoutInMillis = 10; + mVibratorControlService.registerVibratorController(mFakeVibratorController); + CompletableFuture<Void> future = + mVibratorControlService.triggerVibrationParamsRequest(UID, USAGE_RINGTONE, + timeoutInMillis); + CompletableFuture<Void> future2 = + mVibratorControlService.triggerVibrationParamsRequest(UID, USAGE_RINGTONE, + timeoutInMillis); + mTestLooper.dispatchAll(); + + assertThat(future).isNotNull(); + assertThat(future).isEqualTo(future2); + assertThat(future.isDone()).isTrue(); + assertThat(mFakeVibratorController.requestVibrationParamsCounter).isEqualTo(1); + } + + @Test + @RequiresFlagsDisabled(Flags.FLAG_THROTTLE_VIBRATION_PARAMS_REQUESTS) + public void testRequestVibrationParams_withOngoingRequestAndSameUsage_returnNewFuture() { + int timeoutInMillis = 10; + mVibratorControlService.registerVibratorController(mFakeVibratorController); + CompletableFuture<Void> future = + mVibratorControlService.triggerVibrationParamsRequest(UID, USAGE_RINGTONE, + timeoutInMillis); + CompletableFuture<Void> future2 = + mVibratorControlService.triggerVibrationParamsRequest(UID, USAGE_RINGTONE, + timeoutInMillis); + mTestLooper.dispatchAll(); + + assertThat(future).isNotNull(); + assertThat(future2).isNotNull(); + assertThat(future).isNotEqualTo(future2); + assertThat(future.isDone()).isTrue(); + assertThat(future2.isDone()).isTrue(); + assertThat(mFakeVibratorController.requestVibrationParamsCounter).isEqualTo(2); + } + private static int buildVibrationTypesMask(int... types) { int typesMask = 0; for (int type : types) { diff --git a/services/tests/vibrator/src/com/android/server/vibrator/VibratorManagerServiceTest.java b/services/tests/vibrator/src/com/android/server/vibrator/VibratorManagerServiceTest.java index bea691783a8a..e411a178eca4 100644 --- a/services/tests/vibrator/src/com/android/server/vibrator/VibratorManagerServiceTest.java +++ b/services/tests/vibrator/src/com/android/server/vibrator/VibratorManagerServiceTest.java @@ -154,6 +154,9 @@ public class VibratorManagerServiceTest { private static final VibrationAttributes RINGTONE_ATTRS = new VibrationAttributes.Builder().setUsage( VibrationAttributes.USAGE_RINGTONE).build(); + private static final VibrationAttributes IME_FEEDBACK_ATTRS = + new VibrationAttributes.Builder().setUsage( + VibrationAttributes.USAGE_IME_FEEDBACK).build(); private static final VibrationAttributes UNKNOWN_ATTRS = new VibrationAttributes.Builder().setUsage(VibrationAttributes.USAGE_UNKNOWN).build(); @@ -853,6 +856,7 @@ public class VibratorManagerServiceTest { vibrate(service, VibrationEffect.createOneShot(2000, 200), new VibrationAttributes.Builder().setUsage( VibrationAttributes.USAGE_UNKNOWN).build()); + vibrate(service, VibrationEffect.get(VibrationEffect.EFFECT_CLICK), IME_FEEDBACK_ATTRS); InOrder inOrderVerifier = inOrder(mAppOpsManagerMock); inOrderVerifier.verify(mAppOpsManagerMock).checkAudioOpNoThrow(eq(AppOpsManager.OP_VIBRATE), @@ -868,6 +872,8 @@ public class VibratorManagerServiceTest { anyInt(), anyString()); inOrderVerifier.verify(mAppOpsManagerMock).checkAudioOpNoThrow(eq(AppOpsManager.OP_VIBRATE), eq(AudioAttributes.USAGE_UNKNOWN), anyInt(), anyString()); + inOrderVerifier.verify(mAppOpsManagerMock).checkAudioOpNoThrow(eq(AppOpsManager.OP_VIBRATE), + eq(AudioAttributes.USAGE_ASSISTANCE_SONIFICATION), anyInt(), anyString()); } @Test @@ -1684,40 +1690,6 @@ public class VibratorManagerServiceTest { } @Test - public void vibrate_withBypassScaleFlag_ignoresIntensitySettingsAndResolvesAmplitude() - throws Exception { - // Permission needed for bypassing user settings - grantPermission(android.Manifest.permission.MODIFY_PHONE_STATE); - - int defaultTouchIntensity = - mVibrator.getDefaultVibrationIntensity(VibrationAttributes.USAGE_TOUCH); - // This will scale down touch vibrations. - setUserSetting(Settings.System.HAPTIC_FEEDBACK_INTENSITY, - defaultTouchIntensity > Vibrator.VIBRATION_INTENSITY_LOW - ? defaultTouchIntensity - 1 - : defaultTouchIntensity); - - int defaultAmplitude = mContextSpy.getResources().getInteger( - com.android.internal.R.integer.config_defaultVibrationAmplitude); - - mockVibrators(1); - FakeVibratorControllerProvider fakeVibrator = mVibratorProviders.get(1); - fakeVibrator.setCapabilities(IVibrator.CAP_AMPLITUDE_CONTROL); - VibratorManagerService service = createSystemReadyService(); - - vibrateAndWaitUntilFinished(service, - VibrationEffect.createOneShot(100, VibrationEffect.DEFAULT_AMPLITUDE), - new VibrationAttributes.Builder() - .setUsage(VibrationAttributes.USAGE_TOUCH) - .setFlags(VibrationAttributes.FLAG_BYPASS_USER_VIBRATION_INTENSITY_SCALE) - .build()); - - assertEquals(1, fakeVibrator.getAllEffectSegments().size()); - - assertEquals(defaultAmplitude / 255f, fakeVibrator.getAmplitudes().get(0), 1e-5); - } - - @Test @RequiresFlagsEnabled(android.os.vibrator.Flags.FLAG_ADAPTIVE_HAPTICS_ENABLED) public void vibrate_withAdaptiveHaptics_appliesCorrectAdaptiveScales() throws Exception { // Keep user settings the same as device default so only adaptive scale is applied. diff --git a/services/tests/vibrator/utils/com/android/server/vibrator/FakeVibratorController.java b/services/tests/vibrator/utils/com/android/server/vibrator/FakeVibratorController.java index 0cd88ef7a4b4..c0e140738794 100644 --- a/services/tests/vibrator/utils/com/android/server/vibrator/FakeVibratorController.java +++ b/services/tests/vibrator/utils/com/android/server/vibrator/FakeVibratorController.java @@ -39,6 +39,7 @@ public final class FakeVibratorController extends IVibratorController.Stub { public boolean didRequestVibrationParams = false; public int requestVibrationType = VibrationAttributes.USAGE_UNKNOWN; public long requestTimeoutInMillis = 0; + public int requestVibrationParamsCounter = 0; public FakeVibratorController(Looper looper) { mHandler = new Handler(looper); @@ -58,6 +59,7 @@ public final class FakeVibratorController extends IVibratorController.Stub { didRequestVibrationParams = true; requestVibrationType = vibrationType; requestTimeoutInMillis = timeoutInMillis; + requestVibrationParamsCounter++; mHandler.post(() -> { if (mVibratorControlService != null) { mVibratorControlService.onRequestVibrationParamsComplete(token, mRequestResult); diff --git a/services/tests/wmtests/src/com/android/server/wm/ActivityRecordTests.java b/services/tests/wmtests/src/com/android/server/wm/ActivityRecordTests.java index faaa80f0c3e5..ea825c7c0ce4 100644 --- a/services/tests/wmtests/src/com/android/server/wm/ActivityRecordTests.java +++ b/services/tests/wmtests/src/com/android/server/wm/ActivityRecordTests.java @@ -18,10 +18,6 @@ package com.android.server.wm; import static android.app.AppOpsManager.MODE_ALLOWED; import static android.app.AppOpsManager.OP_PICTURE_IN_PICTURE; -import static android.app.CameraCompatTaskInfo.CAMERA_COMPAT_CONTROL_DISMISSED; -import static android.app.CameraCompatTaskInfo.CAMERA_COMPAT_CONTROL_HIDDEN; -import static android.app.CameraCompatTaskInfo.CAMERA_COMPAT_CONTROL_TREATMENT_APPLIED; -import static android.app.CameraCompatTaskInfo.CAMERA_COMPAT_CONTROL_TREATMENT_SUGGESTED; import static android.app.WindowConfiguration.ACTIVITY_TYPE_STANDARD; import static android.app.WindowConfiguration.WINDOWING_MODE_FREEFORM; import static android.app.WindowConfiguration.WINDOWING_MODE_FULLSCREEN; @@ -119,7 +115,6 @@ import static org.mockito.Mockito.never; import android.app.ActivityOptions; import android.app.AppOpsManager; -import android.app.ICompatCameraControlCallback; import android.app.PictureInPictureParams; import android.app.servertransaction.ActivityConfigurationChangeItem; import android.app.servertransaction.ClientTransaction; @@ -3483,178 +3478,6 @@ public class ActivityRecordTests extends WindowTestsBase { assertFalse(app.mActivityRecord.isSurfaceShowing()); } - @Test - public void testUpdateCameraCompatState_flagIsEnabled_controlStateIsUpdated() { - final ActivityRecord activity = createActivityWithTask(); - // Mock a flag being enabled. - doReturn(true).when(activity).isCameraCompatControlEnabled(); - - activity.updateCameraCompatState(/* showControl */ true, - /* transformationApplied */ false, /* callback */ null); - - assertEquals(activity.getCameraCompatControlState(), - CAMERA_COMPAT_CONTROL_TREATMENT_SUGGESTED); - - activity.updateCameraCompatState(/* showControl */ true, - /* transformationApplied */ true, /* callback */ null); - - assertEquals(activity.getCameraCompatControlState(), - CAMERA_COMPAT_CONTROL_TREATMENT_APPLIED); - - activity.updateCameraCompatState(/* showControl */ false, - /* transformationApplied */ false, /* callback */ null); - - assertEquals(activity.getCameraCompatControlState(), CAMERA_COMPAT_CONTROL_HIDDEN); - - activity.updateCameraCompatState(/* showControl */ false, - /* transformationApplied */ true, /* callback */ null); - - assertEquals(activity.getCameraCompatControlState(), CAMERA_COMPAT_CONTROL_HIDDEN); - } - - @Test - public void testUpdateCameraCompatState_flagIsDisabled_controlStateIsHidden() { - final ActivityRecord activity = createActivityWithTask(); - // Mock a flag being disabled. - doReturn(false).when(activity).isCameraCompatControlEnabled(); - - activity.updateCameraCompatState(/* showControl */ true, - /* transformationApplied */ false, /* callback */ null); - - assertEquals(activity.getCameraCompatControlState(), CAMERA_COMPAT_CONTROL_HIDDEN); - - activity.updateCameraCompatState(/* showControl */ true, - /* transformationApplied */ true, /* callback */ null); - - assertEquals(activity.getCameraCompatControlState(), CAMERA_COMPAT_CONTROL_HIDDEN); - } - - @Test - public void testUpdateCameraCompatStateFromUser_clickedOnDismiss() throws RemoteException { - final ActivityRecord activity = createActivityWithTask(); - // Mock a flag being enabled. - doReturn(true).when(activity).isCameraCompatControlEnabled(); - - ICompatCameraControlCallback callback = getCompatCameraControlCallback(); - spyOn(callback); - activity.updateCameraCompatState(/* showControl */ true, - /* transformationApplied */ false, callback); - - assertEquals(activity.getCameraCompatControlState(), - CAMERA_COMPAT_CONTROL_TREATMENT_SUGGESTED); - - // Clicking on the button. - activity.updateCameraCompatStateFromUser(CAMERA_COMPAT_CONTROL_DISMISSED); - - verify(callback, never()).revertCameraCompatTreatment(); - verify(callback, never()).applyCameraCompatTreatment(); - assertEquals(activity.getCameraCompatControlState(), CAMERA_COMPAT_CONTROL_DISMISSED); - - // All following updates are ignored. - activity.updateCameraCompatState(/* showControl */ true, - /* transformationApplied */ false, /* callback */ null); - - assertEquals(activity.getCameraCompatControlState(), CAMERA_COMPAT_CONTROL_DISMISSED); - - activity.updateCameraCompatState(/* showControl */ true, - /* transformationApplied */ true, /* callback */ null); - - assertEquals(activity.getCameraCompatControlState(), CAMERA_COMPAT_CONTROL_DISMISSED); - - activity.updateCameraCompatState(/* showControl */ false, - /* transformationApplied */ true, /* callback */ null); - - assertEquals(activity.getCameraCompatControlState(), CAMERA_COMPAT_CONTROL_DISMISSED); - } - - @Test - public void testUpdateCameraCompatStateFromUser_clickedOnApplyTreatment() - throws RemoteException { - final ActivityRecord activity = createActivityWithTask(); - // Mock a flag being enabled. - doReturn(true).when(activity).isCameraCompatControlEnabled(); - - ICompatCameraControlCallback callback = getCompatCameraControlCallback(); - spyOn(callback); - activity.updateCameraCompatState(/* showControl */ true, - /* transformationApplied */ false, callback); - - assertEquals(activity.getCameraCompatControlState(), - CAMERA_COMPAT_CONTROL_TREATMENT_SUGGESTED); - - // Clicking on the button. - activity.updateCameraCompatStateFromUser(CAMERA_COMPAT_CONTROL_TREATMENT_APPLIED); - - verify(callback, never()).revertCameraCompatTreatment(); - verify(callback).applyCameraCompatTreatment(); - assertEquals(activity.getCameraCompatControlState(), - CAMERA_COMPAT_CONTROL_TREATMENT_APPLIED); - - // Request from the client to show the control are ignored respecting the user choice. - activity.updateCameraCompatState(/* showControl */ true, - /* transformationApplied */ false, /* callback */ null); - - assertEquals(activity.getCameraCompatControlState(), - CAMERA_COMPAT_CONTROL_TREATMENT_APPLIED); - - // Request from the client to hide the control is respected. - activity.updateCameraCompatState(/* showControl */ false, - /* transformationApplied */ true, /* callback */ null); - - assertEquals(activity.getCameraCompatControlState(), CAMERA_COMPAT_CONTROL_HIDDEN); - - // Request from the client to show the control again is respected. - activity.updateCameraCompatState(/* showControl */ true, - /* transformationApplied */ false, /* callback */ null); - - assertEquals(activity.getCameraCompatControlState(), - CAMERA_COMPAT_CONTROL_TREATMENT_SUGGESTED); - } - - @Test - public void testUpdateCameraCompatStateFromUser_clickedOnRevertTreatment() - throws RemoteException { - final ActivityRecord activity = createActivityWithTask(); - // Mock a flag being enabled. - doReturn(true).when(activity).isCameraCompatControlEnabled(); - - ICompatCameraControlCallback callback = getCompatCameraControlCallback(); - spyOn(callback); - activity.updateCameraCompatState(/* showControl */ true, - /* transformationApplied */ true, callback); - - assertEquals(activity.getCameraCompatControlState(), - CAMERA_COMPAT_CONTROL_TREATMENT_APPLIED); - - // Clicking on the button. - activity.updateCameraCompatStateFromUser(CAMERA_COMPAT_CONTROL_TREATMENT_SUGGESTED); - - verify(callback).revertCameraCompatTreatment(); - verify(callback, never()).applyCameraCompatTreatment(); - assertEquals(activity.getCameraCompatControlState(), - CAMERA_COMPAT_CONTROL_TREATMENT_SUGGESTED); - - // Request from the client to show the control are ignored respecting the user choice. - activity.updateCameraCompatState(/* showControl */ true, - /* transformationApplied */ true, /* callback */ null); - - assertEquals(activity.getCameraCompatControlState(), - CAMERA_COMPAT_CONTROL_TREATMENT_SUGGESTED); - - // Request from the client to hide the control is respected. - activity.updateCameraCompatState(/* showControl */ false, - /* transformationApplied */ true, /* callback */ null); - - assertEquals(activity.getCameraCompatControlState(), CAMERA_COMPAT_CONTROL_HIDDEN); - - // Request from the client to show the control again is respected. - activity.updateCameraCompatState(/* showControl */ true, - /* transformationApplied */ true, /* callback */ null); - - assertEquals(activity.getCameraCompatControlState(), - CAMERA_COMPAT_CONTROL_TREATMENT_APPLIED); - } - @Test // b/162542125 public void testInputDispatchTimeout() throws RemoteException { final ActivityRecord activity = createActivityWithTask(); @@ -3818,16 +3641,6 @@ public class ActivityRecordTests extends WindowTestsBase { assertTrue(appWindow.mResizeReported); } - private ICompatCameraControlCallback getCompatCameraControlCallback() { - return new ICompatCameraControlCallback.Stub() { - @Override - public void applyCameraCompatTreatment() {} - - @Override - public void revertCameraCompatTreatment() {} - }; - } - private void assertHasStartingWindow(ActivityRecord atoken) { assertNotNull(atoken.mStartingSurface); assertNotNull(atoken.mStartingData); diff --git a/services/tests/wmtests/src/com/android/server/wm/ActivityStarterTests.java b/services/tests/wmtests/src/com/android/server/wm/ActivityStarterTests.java index ff1c6c8fc70c..d0080d29f82b 100644 --- a/services/tests/wmtests/src/com/android/server/wm/ActivityStarterTests.java +++ b/services/tests/wmtests/src/com/android/server/wm/ActivityStarterTests.java @@ -102,6 +102,7 @@ import android.provider.DeviceConfig; import android.service.voice.IVoiceInteractionSession; import android.util.Pair; import android.util.Size; +import android.view.Display; import android.view.Gravity; import android.view.RemoteAnimationAdapter; import android.window.TaskFragmentOrganizerToken; @@ -941,6 +942,91 @@ public class ActivityStarterTests extends WindowTestsBase { notNull() /* options */); } + + /** + * This test ensures that activity launch on a secondary display is allowed if the activity did + * not opt out from showing on remote devices. + */ + @Test + public void testStartActivityOnVirtualDisplay() { + final ActivityStarter starter = prepareStarter(FLAG_ACTIVITY_NEW_TASK, + false /* mockGetRootTask */); + starter.mRequest.activityInfo.flags |= ActivityInfo.FLAG_CAN_DISPLAY_ON_REMOTE_DEVICES; + + // Create a virtual display at bottom. + final TestDisplayContent secondaryDisplay = + new TestDisplayContent.Builder(mAtm, 1000, 1500) + .setType(Display.TYPE_VIRTUAL) + .setPosition(POSITION_BOTTOM).build(); + final TaskDisplayArea secondaryTaskContainer = secondaryDisplay.getDefaultTaskDisplayArea(); + final Task stack = secondaryTaskContainer.createRootTask( + WINDOWING_MODE_FULLSCREEN, ACTIVITY_TYPE_STANDARD, true /* onTop */); + + // Create an activity record on the top of secondary display. + final ActivityRecord topActivityOnSecondaryDisplay = createSingleTaskActivityOn(stack); + + // Put an activity on default display as the top focused activity. + new ActivityBuilder(mAtm).setCreateTask(true).build(); + + // Start activity with the same intent as {@code topActivityOnSecondaryDisplay} + // on secondary display. + final ActivityOptions options = ActivityOptions.makeBasic() + .setLaunchDisplayId(secondaryDisplay.mDisplayId); + final int result = starter.setReason("testStartActivityOnVirtualDisplay") + .setIntent(topActivityOnSecondaryDisplay.intent) + .setActivityOptions(options.toBundle()) + .execute(); + + // Ensure result is delivering intent to top. + assertEquals(START_DELIVERED_TO_TOP, result); + + // Ensure secondary display only creates one stack. + verify(secondaryTaskContainer, times(1)).createRootTask(anyInt(), anyInt(), anyBoolean()); + } + + /** + * This test ensures that activity launch on a secondary display is disallowed if the activity + * opted out from showing on remote devices. + */ + @EnableFlags(android.companion.virtualdevice.flags.Flags + .FLAG_ENFORCE_REMOTE_DEVICE_OPT_OUT_ON_ALL_VIRTUAL_DISPLAYS) + @Test + public void testStartOptedOutActivityOnVirtualDisplay() { + final ActivityStarter starter = prepareStarter(FLAG_ACTIVITY_NEW_TASK, + false /* mockGetRootTask */); + starter.mRequest.activityInfo.flags &= ~ActivityInfo.FLAG_CAN_DISPLAY_ON_REMOTE_DEVICES; + + // Create a virtual display at bottom. + final TestDisplayContent secondaryDisplay = + new TestDisplayContent.Builder(mAtm, 1000, 1500) + .setType(Display.TYPE_VIRTUAL) + .setPosition(POSITION_BOTTOM).build(); + final TaskDisplayArea secondaryTaskContainer = secondaryDisplay.getDefaultTaskDisplayArea(); + final Task stack = secondaryTaskContainer.createRootTask( + WINDOWING_MODE_FULLSCREEN, ACTIVITY_TYPE_STANDARD, true /* onTop */); + + // Create an activity record on the top of secondary display. + final ActivityRecord topActivityOnSecondaryDisplay = createSingleTaskActivityOn(stack); + + // Put an activity on default display as the top focused activity. + new ActivityBuilder(mAtm).setCreateTask(true).build(); + + // Start activity with the same intent as {@code topActivityOnSecondaryDisplay} + // on secondary display. + final ActivityOptions options = ActivityOptions.makeBasic() + .setLaunchDisplayId(secondaryDisplay.mDisplayId); + final int result = starter.setReason("testStartOptedOutActivityOnVirtualDisplay") + .setIntent(topActivityOnSecondaryDisplay.intent) + .setActivityOptions(options.toBundle()) + .execute(); + + // Ensure result is canceled. + assertEquals(START_CANCELED, result); + + // Ensure secondary display only creates one stack. + verify(secondaryTaskContainer, times(1)).createRootTask(anyInt(), anyInt(), anyBoolean()); + } + @Test public void testWasVisibleInRestartAttempt() { final ActivityStarter starter = prepareStarter( diff --git a/services/tests/wmtests/src/com/android/server/wm/AppCompatAspectRatioOverridesTest.java b/services/tests/wmtests/src/com/android/server/wm/AppCompatAspectRatioOverridesTest.java index ddd6d562abb1..a6fd11210307 100644 --- a/services/tests/wmtests/src/com/android/server/wm/AppCompatAspectRatioOverridesTest.java +++ b/services/tests/wmtests/src/com/android/server/wm/AppCompatAspectRatioOverridesTest.java @@ -26,6 +26,7 @@ import static android.view.WindowManager.PROPERTY_COMPAT_ALLOW_USER_ASPECT_RATIO import static com.android.dx.mockito.inline.extended.ExtendedMockito.spyOn; import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertNotEquals; import android.compat.testing.PlatformCompatChangeRule; import android.platform.test.annotations.Presubmit; @@ -246,7 +247,6 @@ public class AppCompatAspectRatioOverridesTest extends WindowTestsBase { }); } - @Test @EnableCompatChanges({OVERRIDE_MIN_ASPECT_RATIO}) public void testshouldOverrideMinAspectRatio_propertyFalse_overrideEnabled_returnsFalse() { @@ -269,6 +269,24 @@ public class AppCompatAspectRatioOverridesTest extends WindowTestsBase { }); } + @Test + public void testGetFixedOrientationLetterboxAspectRatio_splitScreenAspectEnabled() { + runTestScenario((robot)-> { + robot.applyOnConf((c) -> { + c.enableCameraCompatTreatment(/* enabled */ true); + c.enableCameraCompatTreatmentAtBuildTime(/* enabled */ true); + c.enableCameraCompatSplitScreenAspectRatio(/* enabled */ true); + c.enableDisplayAspectRatioEnabledForFixedOrientationLetterbox(/* enabled */ false); + c.setFixedOrientationLetterboxAspectRatio(/* aspectRatio */ 1.5f); + }); + robot.activity().createActivityWithComponentInNewTaskAndDisplay(); + robot.checkFixedOrientationLetterboxAspectRatioForTopParent(/* expected */ 1.5f); + + robot.activity().enableTreatmentForTopActivity(/* enabled */ true); + robot.checkAspectRatioForTopParentIsSplitScreenRatio(/* expected */ true); + }); + } + /** * Runs a test scenario providing a Robot. */ @@ -308,6 +326,28 @@ public class AppCompatAspectRatioOverridesTest extends WindowTestsBase { } @NonNull + void checkFixedOrientationLetterboxAspectRatioForTopParent(float expected) { + assertEquals(expected, + getTopActivityAppCompatAspectRatioOverrides() + .getFixedOrientationLetterboxAspectRatio( + activity().top().getParent().getConfiguration()), + FLOAT_TOLLERANCE); + } + + void checkAspectRatioForTopParentIsSplitScreenRatio(boolean expected) { + final AppCompatAspectRatioOverrides aspectRatioOverrides = + getTopActivityAppCompatAspectRatioOverrides(); + if (expected) { + assertEquals(aspectRatioOverrides.getSplitScreenAspectRatio(), + aspectRatioOverrides.getFixedOrientationLetterboxAspectRatio( + activity().top().getParent().getConfiguration()), FLOAT_TOLLERANCE); + } else { + assertNotEquals(aspectRatioOverrides.getSplitScreenAspectRatio(), + aspectRatioOverrides.getFixedOrientationLetterboxAspectRatio( + activity().top().getParent().getConfiguration()), FLOAT_TOLLERANCE); + } + } + private AppCompatAspectRatioOverrides getTopActivityAppCompatAspectRatioOverrides() { return activity().top().mAppCompatController.getAppCompatAspectRatioOverrides(); } diff --git a/services/tests/wmtests/src/com/android/server/wm/AppCompatConfigurationRobot.java b/services/tests/wmtests/src/com/android/server/wm/AppCompatConfigurationRobot.java index 00a87719eaac..6592f2625ab6 100644 --- a/services/tests/wmtests/src/com/android/server/wm/AppCompatConfigurationRobot.java +++ b/services/tests/wmtests/src/com/android/server/wm/AppCompatConfigurationRobot.java @@ -70,4 +70,14 @@ class AppCompatConfigurationRobot { void enableCompatFakeFocus(boolean enabled) { doReturn(enabled).when(mAppCompatConfiguration).isCompatFakeFocusEnabled(); } + + void enableDisplayAspectRatioEnabledForFixedOrientationLetterbox(boolean enabled) { + doReturn(enabled).when(mAppCompatConfiguration) + .getIsDisplayAspectRatioEnabledForFixedOrientationLetterbox(); + } + + void setFixedOrientationLetterboxAspectRatio(float aspectRatio) { + doReturn(aspectRatio).when(mAppCompatConfiguration) + .getFixedOrientationLetterboxAspectRatio(); + } } diff --git a/services/tests/wmtests/src/com/android/server/wm/AppCompatRobotBase.java b/services/tests/wmtests/src/com/android/server/wm/AppCompatRobotBase.java index 92f246be7cdf..6939f97e1799 100644 --- a/services/tests/wmtests/src/com/android/server/wm/AppCompatRobotBase.java +++ b/services/tests/wmtests/src/com/android/server/wm/AppCompatRobotBase.java @@ -28,6 +28,8 @@ abstract class AppCompatRobotBase { private static final int DEFAULT_DISPLAY_WIDTH = 1000; private static final int DEFAULT_DISPLAY_HEIGHT = 2000; + static final float FLOAT_TOLLERANCE = 0.01f; + @NonNull private final AppCompatActivityRobot mActivityRobot; @NonNull diff --git a/services/tests/wmtests/src/com/android/server/wm/BackNavigationControllerTests.java b/services/tests/wmtests/src/com/android/server/wm/BackNavigationControllerTests.java index afa22bc5eae8..a159ce354a7b 100644 --- a/services/tests/wmtests/src/com/android/server/wm/BackNavigationControllerTests.java +++ b/services/tests/wmtests/src/com/android/server/wm/BackNavigationControllerTests.java @@ -72,7 +72,6 @@ import android.window.TaskSnapshot; import android.window.WindowOnBackInvokedDispatcher; import com.android.server.LocalServices; -import com.android.window.flags.Flags; import org.junit.Before; import org.junit.Test; @@ -672,7 +671,6 @@ public class BackNavigationControllerTests extends WindowTestsBase { @Test public void testBackOnMostRecentWindowInActivityEmbedding() { - mSetFlagsRule.enableFlags(Flags.FLAG_EMBEDDED_ACTIVITY_BACK_NAV_FLAG); final Task task = createTask(mDefaultDisplay); final TaskFragmentOrganizer organizer = new TaskFragmentOrganizer(Runnable::run); final TaskFragment primaryTf = createTaskFragmentWithEmbeddedActivity(task, organizer); diff --git a/services/tests/wmtests/src/com/android/server/wm/BackgroundActivityStartControllerExemptionTests.java b/services/tests/wmtests/src/com/android/server/wm/BackgroundActivityStartControllerExemptionTests.java index 366e519fb063..6e488188eb87 100644 --- a/services/tests/wmtests/src/com/android/server/wm/BackgroundActivityStartControllerExemptionTests.java +++ b/services/tests/wmtests/src/com/android/server/wm/BackgroundActivityStartControllerExemptionTests.java @@ -16,6 +16,9 @@ package com.android.server.wm; +import static android.app.ActivityOptions.MODE_BACKGROUND_ACTIVITY_START_ALLOWED; +import static android.app.ActivityOptions.MODE_BACKGROUND_ACTIVITY_START_ALLOW_ALWAYS; + import static com.android.server.wm.ActivityTaskManagerService.APP_SWITCH_ALLOW; import static com.android.server.wm.BackgroundActivityStartController.BAL_ALLOW_ALLOWLISTED_COMPONENT; import static com.android.server.wm.BackgroundActivityStartController.BAL_ALLOW_FOREGROUND; @@ -23,7 +26,6 @@ import static com.android.server.wm.BackgroundActivityStartController.BAL_ALLOW_ import static com.android.server.wm.BackgroundActivityStartController.BAL_ALLOW_SAW_PERMISSION; import static com.android.server.wm.BackgroundActivityStartController.BAL_ALLOW_VISIBLE_WINDOW; -import static com.google.common.truth.Truth.assertThat; import static com.google.common.truth.Truth.assertWithMessage; import static org.mockito.ArgumentMatchers.anyInt; @@ -58,7 +60,6 @@ import org.junit.Test; import org.junit.runner.RunWith; import org.junit.runners.JUnit4; import org.mockito.Mock; -import org.mockito.Mockito; import org.mockito.quality.Strictness; import java.lang.reflect.Field; @@ -134,9 +135,8 @@ public class BackgroundActivityStartControllerExemptionTests { ActivityOptions mCheckedOptions = ActivityOptions.makeBasic() .setPendingIntentCreatorBackgroundActivityStartMode( - ActivityOptions.MODE_BACKGROUND_ACTIVITY_START_ALLOWED) - .setPendingIntentBackgroundActivityStartMode( - ActivityOptions.MODE_BACKGROUND_ACTIVITY_START_ALLOWED); + MODE_BACKGROUND_ACTIVITY_START_ALLOWED) + .setPendingIntentBackgroundActivityStartMode(MODE_BACKGROUND_ACTIVITY_START_ALLOWED); class TestableBackgroundActivityStartController extends BackgroundActivityStartController { private Set<Pair<Integer, Integer>> mBalPermissionUidPidPairs = new HashSet<>(); @@ -175,7 +175,6 @@ public class BackgroundActivityStartControllerExemptionTests { when(mService.getAppOpsManager()).thenReturn(mAppOpsManager); setViaReflection(mService, "mProcessMap", mProcessMap); - //Mockito.when(mSupervisor.getBackgroundActivityLaunchController()).thenReturn(mController); setViaReflection(mSupervisor, "mRecentTasks", mRecentTasks); mController = new TestableBackgroundActivityStartController(mService, mSupervisor); @@ -397,7 +396,7 @@ public class BackgroundActivityStartControllerExemptionTests { // setup state WindowProcessControllerMap mProcessMap = new WindowProcessControllerMap(); - WindowProcessController otherProcess = Mockito.mock(WindowProcessController.class); + WindowProcessController otherProcess = mock(WindowProcessController.class); mProcessMap.put(callingPid, mCallerApp); mProcessMap.put(REGULAR_PID_1_1, otherProcess); setViaReflection(mService, "mProcessMap", mProcessMap); @@ -516,14 +515,13 @@ public class BackgroundActivityStartControllerExemptionTests { BackgroundStartPrivileges forcedBalByPiSender = BackgroundStartPrivileges.NONE; Intent intent = TEST_INTENT; ActivityOptions checkedOptions = mCheckedOptions; - checkedOptions.setPendingIntentBackgroundActivityLaunchAllowedByPermission(true); + checkedOptions.setPendingIntentBackgroundActivityStartMode( + MODE_BACKGROUND_ACTIVITY_START_ALLOW_ALWAYS); BackgroundActivityStartController.BalState balState = mController.new BalState(callingUid, callingPid, callingPackage, realCallingUid, realCallingPid, null, originatingPendingIntent, forcedBalByPiSender, mResultRecord, intent, checkedOptions); - assertThat(balState.isPendingIntentBalAllowedByPermission()).isTrue(); - // call BalVerdict realCallerVerdict = mController.checkBackgroundActivityStartAllowedBySender( balState); diff --git a/services/tests/wmtests/src/com/android/server/wm/BackgroundActivityStartControllerTests.java b/services/tests/wmtests/src/com/android/server/wm/BackgroundActivityStartControllerTests.java index f110c69b57f5..e364264fc74f 100644 --- a/services/tests/wmtests/src/com/android/server/wm/BackgroundActivityStartControllerTests.java +++ b/services/tests/wmtests/src/com/android/server/wm/BackgroundActivityStartControllerTests.java @@ -547,7 +547,7 @@ public class BackgroundActivityStartControllerTests { assertThat(balState.callerExplicitOptInOrOut()).isFalse(); assertThat(balState.realCallerExplicitOptInOrAutoOptIn()).isTrue(); assertThat(balState.realCallerExplicitOptInOrOut()).isFalse(); - assertThat(balState.toString()).contains( + assertThat(balState.toString()).startsWith( "[callingPackage: package.app1; " + "callingPackageTargetSdk: -1; " + "callingUid: 10001; " @@ -563,6 +563,7 @@ public class BackgroundActivityStartControllerTests { + "balAllowedByPiCreator: BSP.ALLOW_BAL; " + "balAllowedByPiCreatorWithHardening: BSP.ALLOW_BAL; " + "resultIfPiCreatorAllowsBal: null; " + + "callerStartMode: MODE_BACKGROUND_ACTIVITY_START_SYSTEM_DEFINED; " + "hasRealCaller: true; " + "isCallForResult: false; " + "isPendingIntent: false; " @@ -646,7 +647,7 @@ public class BackgroundActivityStartControllerTests { assertThat(balState.callerExplicitOptInOrOut()).isFalse(); assertThat(balState.realCallerExplicitOptInOrAutoOptIn()).isFalse(); assertThat(balState.realCallerExplicitOptInOrOut()).isFalse(); - assertThat(balState.toString()).contains( + assertThat(balState.toString()).startsWith( "[callingPackage: package.app1; " + "callingPackageTargetSdk: -1; " + "callingUid: 10001; " @@ -662,6 +663,7 @@ public class BackgroundActivityStartControllerTests { + "balAllowedByPiCreator: BSP.NONE; " + "balAllowedByPiCreatorWithHardening: BSP.NONE; " + "resultIfPiCreatorAllowsBal: null; " + + "callerStartMode: MODE_BACKGROUND_ACTIVITY_START_SYSTEM_DEFINED; " + "hasRealCaller: true; " + "isCallForResult: false; " + "isPendingIntent: true; " diff --git a/services/tests/wmtests/src/com/android/server/wm/DisplayContentDeferredUpdateTests.java b/services/tests/wmtests/src/com/android/server/wm/DisplayContentDeferredUpdateTests.java index 57118f236815..f84338656436 100644 --- a/services/tests/wmtests/src/com/android/server/wm/DisplayContentDeferredUpdateTests.java +++ b/services/tests/wmtests/src/com/android/server/wm/DisplayContentDeferredUpdateTests.java @@ -63,11 +63,6 @@ public class DisplayContentDeferredUpdateTests extends WindowTestsBase { private final Message mScreenUnblocker = mock(Message.class); - @Override - protected void onBeforeSystemServicesCreated() { - mSetFlagsRule.enableFlags(Flags.FLAG_DEFER_DISPLAY_UPDATES); - } - @Before public void before() { doReturn(true).when(mDisplayContent).getLastHasContent(); diff --git a/services/tests/wmtests/src/com/android/server/wm/DisplayWindowSettingsProviderTests.java b/services/tests/wmtests/src/com/android/server/wm/DisplayWindowSettingsProviderTests.java index 3fcf3042ab94..2e0d4d46ec05 100644 --- a/services/tests/wmtests/src/com/android/server/wm/DisplayWindowSettingsProviderTests.java +++ b/services/tests/wmtests/src/com/android/server/wm/DisplayWindowSettingsProviderTests.java @@ -24,12 +24,15 @@ import static android.view.WindowManager.DISPLAY_IME_POLICY_LOCAL; import static androidx.test.platform.app.InstrumentationRegistry.getInstrumentation; +import static com.android.dx.mockito.inline.extended.ExtendedMockito.doReturn; + import static com.google.common.truth.Truth.assertThat; import static org.junit.Assert.assertEquals; import static org.junit.Assert.assertNotEquals; import static org.junit.Assert.assertTrue; import static org.junit.Assume.assumeTrue; +import static org.mockito.ArgumentMatchers.eq; import static org.testng.Assert.assertFalse; import android.annotation.Nullable; @@ -58,6 +61,7 @@ import java.io.IOException; import java.io.InputStream; import java.io.OutputStream; import java.nio.charset.StandardCharsets; +import java.util.List; import java.util.function.Consumer; /** @@ -352,20 +356,58 @@ public class DisplayWindowSettingsProviderTests extends WindowTestsBase { } @Test - public void testRemovesStaleDisplaySettings() { + public void testRemovesStaleDisplaySettings_defaultDisplay_removesStaleDisplaySettings() { assumeTrue(com.android.window.flags.Flags.perUserDisplayWindowSettings()); - final DisplayWindowSettingsProvider provider = - new DisplayWindowSettingsProvider(mDefaultVendorSettingsStorage, - mOverrideSettingsStorage); - final DisplayInfo displayInfo = mSecondaryDisplay.getDisplayInfo(); - updateOverrideSettings(provider, displayInfo, settings -> settings.mForcedDensity = 356); + // Write density setting for second display then remove it. + final DisplayWindowSettingsProvider provider = new DisplayWindowSettingsProvider( + mDefaultVendorSettingsStorage, mOverrideSettingsStorage); + final DisplayInfo secDisplayInfo = mSecondaryDisplay.getDisplayInfo(); + updateOverrideSettings(provider, secDisplayInfo, setting -> setting.mForcedDensity = 356); mRootWindowContainer.removeChild(mSecondaryDisplay); - provider.removeStaleDisplaySettings(mRootWindowContainer); + // Write density setting for inner and outer default display. + final DisplayInfo innerDisplayInfo = mPrimaryDisplay.getDisplayInfo(); + final DisplayInfo outerDisplayInfo = new DisplayInfo(secDisplayInfo); + outerDisplayInfo.displayId = mPrimaryDisplay.mDisplayId; + outerDisplayInfo.uniqueId = "TEST_OUTER_DISPLAY_" + System.currentTimeMillis(); + updateOverrideSettings(provider, innerDisplayInfo, setting -> setting.mForcedDensity = 490); + updateOverrideSettings(provider, outerDisplayInfo, setting -> setting.mForcedDensity = 420); + final List<DisplayInfo> possibleDisplayInfos = List.of(innerDisplayInfo, outerDisplayInfo); + doReturn(possibleDisplayInfos) + .when(mWm).getPossibleDisplayInfoLocked(eq(innerDisplayInfo.displayId)); + + provider.removeStaleDisplaySettingsLocked(mWm, mRootWindowContainer); + + assertThat(mOverrideSettingsStorage.wasWriteSuccessful()).isTrue(); + assertThat(provider.getOverrideSettingsSize()).isEqualTo(2); + assertThat(provider.getOverrideSettings(innerDisplayInfo).mForcedDensity).isEqualTo(490); + assertThat(provider.getOverrideSettings(outerDisplayInfo).mForcedDensity).isEqualTo(420); + } + + @Test + public void testRemovesStaleDisplaySettings_displayNotInLayout_keepsDisplaySettings() { + assumeTrue(com.android.window.flags.Flags.perUserDisplayWindowSettings()); + + // Write density setting for primary display. + final DisplayWindowSettingsProvider provider = new DisplayWindowSettingsProvider( + mDefaultVendorSettingsStorage, mOverrideSettingsStorage); + final DisplayInfo primDisplayInfo = mPrimaryDisplay.getDisplayInfo(); + updateOverrideSettings(provider, primDisplayInfo, setting -> setting.mForcedDensity = 420); + + // Add a virtual display and write density setting for it. + final DisplayInfo virtDisplayInfo = new DisplayInfo(primDisplayInfo); + virtDisplayInfo.uniqueId = "TEST_VIRTUAL_DISPLAY_" + System.currentTimeMillis(); + createNewDisplay(virtDisplayInfo); + waitUntilHandlersIdle(); // Wait until unfrozen after a display is added. + updateOverrideSettings(provider, virtDisplayInfo, setting -> setting.mForcedDensity = 490); + + provider.removeStaleDisplaySettingsLocked(mWm, mRootWindowContainer); assertThat(mOverrideSettingsStorage.wasWriteSuccessful()).isTrue(); - assertThat(provider.getOverrideSettingsSize()).isEqualTo(0); + assertThat(provider.getOverrideSettingsSize()).isEqualTo(2); + assertThat(provider.getOverrideSettings(primDisplayInfo).mForcedDensity).isEqualTo(420); + assertThat(provider.getOverrideSettings(virtDisplayInfo).mForcedDensity).isEqualTo(490); } /** diff --git a/services/tests/wmtests/src/com/android/server/wm/DragDropControllerTests.java b/services/tests/wmtests/src/com/android/server/wm/DragDropControllerTests.java index e5650068c8fb..4a9d5c7bc828 100644 --- a/services/tests/wmtests/src/com/android/server/wm/DragDropControllerTests.java +++ b/services/tests/wmtests/src/com/android/server/wm/DragDropControllerTests.java @@ -156,7 +156,6 @@ public class DragDropControllerTests extends WindowTestsBase { window.openInputChannel(channel); window.mHasSurface = true; mWm.mWindowMap.put(window.mClient.asBinder(), window); - mWm.mInputToWindowMap.put(window.mInputChannelToken, window); return window; } @@ -179,7 +178,7 @@ public class DragDropControllerTests extends WindowTestsBase { mWindow = createDropTargetWindow("Drag test window", 0); doReturn(mWindow).when(mDisplayContent).getTouchableWinAtPointLocked(0, 0); when(mWm.mInputManager.startDragAndDrop(any(IBinder.class), - any(InputChannel.class))).thenReturn(true); + any(IBinder.class))).thenReturn(true); mWm.mWindowMap.put(mWindow.mClient.asBinder(), mWindow); } @@ -707,7 +706,7 @@ public class DragDropControllerTests extends WindowTestsBase { .setFormat(PixelFormat.TRANSLUCENT) .build(); - assertTrue(mWm.mInputManager.startDragAndDrop(new Binder(), new InputChannel())); + assertTrue(mWm.mInputManager.startDragAndDrop(new Binder(), new Binder())); mToken = mTarget.performDrag(TEST_PID, 0, mWindow.mClient, flag, surface, 0, 0, 0, 0, 0, 0, 0, data); assertNotNull(mToken); 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 e2c0f6c20c01..61a6f316244c 100644 --- a/services/tests/wmtests/src/com/android/server/wm/LetterboxUiControllerTest.java +++ b/services/tests/wmtests/src/com/android/server/wm/LetterboxUiControllerTest.java @@ -19,7 +19,6 @@ package com.android.server.wm; import static android.view.InsetsSource.FLAG_INSETS_ROUNDED_CORNER; import static com.android.dx.mockito.inline.extended.ExtendedMockito.doReturn; -import static com.android.dx.mockito.inline.extended.ExtendedMockito.eq; import static com.android.dx.mockito.inline.extended.ExtendedMockito.mock; import static com.android.dx.mockito.inline.extended.ExtendedMockito.spyOn; @@ -297,37 +296,6 @@ public class LetterboxUiControllerTest extends WindowTestsBase { } @Test - public void testgetFixedOrientationLetterboxAspectRatio_splitScreenAspectEnabled() { - doReturn(true).when(mActivity.mWmService.mAppCompatConfiguration) - .isCameraCompatTreatmentEnabled(); - doReturn(true).when(mActivity.mWmService.mAppCompatConfiguration) - .isCameraCompatTreatmentEnabledAtBuildTime(); - doReturn(true).when(mActivity.mWmService.mAppCompatConfiguration) - .isCameraCompatSplitScreenAspectRatioEnabled(); - doReturn(false).when(mActivity.mWmService.mAppCompatConfiguration) - .getIsDisplayAspectRatioEnabledForFixedOrientationLetterbox(); - doReturn(1.5f).when(mActivity.mWmService.mAppCompatConfiguration) - .getFixedOrientationLetterboxAspectRatio(); - - // Recreate DisplayContent with DisplayRotationCompatPolicy - mActivity = setUpActivityWithComponent(); - mController = new LetterboxUiController(mWm, mActivity); - - assertEquals(1.5f, mController.getFixedOrientationLetterboxAspectRatio( - mActivity.getParent().getConfiguration()), /* delta */ 0.01); - - spyOn(mDisplayContent.mAppCompatCameraPolicy); - doReturn(true).when(mDisplayContent.mAppCompatCameraPolicy) - .isTreatmentEnabledForActivity(eq(mActivity)); - - final AppCompatAspectRatioOverrides aspectRatioOverrides = - mActivity.mAppCompatController.getAppCompatAspectRatioOverrides(); - assertEquals(aspectRatioOverrides.getSplitScreenAspectRatio(), - aspectRatioOverrides.getFixedOrientationLetterboxAspectRatio( - mActivity.getParent().getConfiguration()), /* delta */ 0.01); - } - - @Test public void testIsVerticalThinLetterboxed() { // Vertical thin letterbox disabled doReturn(-1).when(mActivity.mWmService.mAppCompatConfiguration) diff --git a/services/tests/wmtests/src/com/android/server/wm/PhysicalDisplaySwitchTransitionLauncherTest.java b/services/tests/wmtests/src/com/android/server/wm/PhysicalDisplaySwitchTransitionLauncherTest.java deleted file mode 100644 index 78509dbfdb1a..000000000000 --- a/services/tests/wmtests/src/com/android/server/wm/PhysicalDisplaySwitchTransitionLauncherTest.java +++ /dev/null @@ -1,283 +0,0 @@ -/* - * Copyright (C) 2023 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package com.android.server.wm; - -import static com.android.internal.R.bool.config_unfoldTransitionEnabled; -import static com.android.server.wm.DeviceStateController.DeviceState.REAR; -import static com.android.server.wm.DeviceStateController.DeviceState.FOLDED; -import static com.android.server.wm.DeviceStateController.DeviceState.HALF_FOLDED; -import static com.android.server.wm.DeviceStateController.DeviceState.OPEN; - -import static org.junit.Assert.assertEquals; -import static org.junit.Assert.assertNotNull; -import static org.junit.Assert.assertNull; -import static org.junit.Assert.assertTrue; -import static org.mockito.Mockito.when; - -import android.animation.ValueAnimator; -import android.content.Context; -import android.content.res.Resources; -import android.graphics.Rect; -import android.platform.test.annotations.Presubmit; - -import androidx.test.filters.SmallTest; - -import org.junit.After; -import org.junit.Before; -import org.junit.Test; -import org.junit.runner.RunWith; -import org.mockito.Mock; -import org.mockito.MockitoAnnotations; - -/** - * Tests for the {@link WindowToken} class. - * - * Build/Install/Run: - * atest WmTests:PhysicalDisplaySwitchTransitionLauncherTest - */ -@SmallTest -@Presubmit -@RunWith(WindowTestRunner.class) -public class PhysicalDisplaySwitchTransitionLauncherTest extends WindowTestsBase { - - @Mock - Context mContext; - @Mock - Resources mResources; - @Mock - BLASTSyncEngine mSyncEngine; - - WindowTestsBase.TestTransitionPlayer mPlayer; - TransitionController mTransitionController; - DisplayContent mDisplayContent; - - private PhysicalDisplaySwitchTransitionLauncher mTarget; - private float mOriginalAnimationScale; - - @Before - public void setUp() { - MockitoAnnotations.initMocks(this); - mTransitionController = new WindowTestsBase.TestTransitionController(mAtm); - mTransitionController.setSyncEngine(mSyncEngine); - mPlayer = new WindowTestsBase.TestTransitionPlayer( - mTransitionController, mAtm.mWindowOrganizerController); - when(mContext.getResources()).thenReturn(mResources); - mDisplayContent = new TestDisplayContent.Builder(mAtm, 100, 150).build(); - mTarget = new PhysicalDisplaySwitchTransitionLauncher(mDisplayContent, mAtm, mContext, - mTransitionController); - mOriginalAnimationScale = ValueAnimator.getDurationScale(); - } - - @After - public void after() { - ValueAnimator.setDurationScale(mOriginalAnimationScale); - } - - @Test - public void testDisplaySwitchAfterUnfoldToOpen_animationsEnabled_requestsTransition() { - givenAllAnimationsEnabled(); - mTarget.foldStateChanged(FOLDED); - - mTarget.foldStateChanged(OPEN); - final Rect origBounds = new Rect(); - mDisplayContent.getBounds(origBounds); - origBounds.offsetTo(0, 0); - mTarget.requestDisplaySwitchTransitionIfNeeded( - mDisplayContent.getDisplayId(), - origBounds.width(), - origBounds.height(), - /* newDisplayWidth= */ 200, - /* newDisplayHeight= */ 250 - ); - - assertNotNull(mPlayer.mLastRequest); - assertEquals(mDisplayContent.getDisplayId(), - mPlayer.mLastRequest.getDisplayChange().getDisplayId()); - assertEquals(origBounds, mPlayer.mLastRequest.getDisplayChange().getStartAbsBounds()); - assertEquals(new Rect(0, 0, 200, 250), - mPlayer.mLastRequest.getDisplayChange().getEndAbsBounds()); - } - - @Test - public void testDisplaySwitchAfterFolding_animationEnabled_doesNotRequestTransition() { - givenAllAnimationsEnabled(); - mTarget.foldStateChanged(OPEN); - - mTarget.foldStateChanged(FOLDED); - requestDisplaySwitch(); - - assertTransitionNotRequested(); - } - - @Test - public void testDisplaySwitchAfterUnfoldingToHalf_animationEnabled_requestsTransition() { - givenAllAnimationsEnabled(); - mTarget.foldStateChanged(FOLDED); - - mTarget.foldStateChanged(HALF_FOLDED); - requestDisplaySwitch(); - - assertTransitionRequested(); - } - - @Test - public void testDisplaySwitchSecondTimeAfterUnfolding_animationEnabled_noTransition() { - givenAllAnimationsEnabled(); - mTarget.foldStateChanged(FOLDED); - mTarget.foldStateChanged(OPEN); - requestDisplaySwitch(); - mPlayer.mLastRequest = null; - - requestDisplaySwitch(); - - assertTransitionNotRequested(); - } - - - @Test - public void testDisplaySwitchAfterGoingToRearAndBack_animationEnabled_noTransition() { - givenAllAnimationsEnabled(); - mTarget.foldStateChanged(OPEN); - - mTarget.foldStateChanged(REAR); - mTarget.foldStateChanged(OPEN); - requestDisplaySwitch(); - - assertTransitionNotRequested(); - } - - @Test - public void testDisplaySwitchAfterUnfoldingAndFolding_animationEnabled_noTransition() { - givenAllAnimationsEnabled(); - mTarget.foldStateChanged(FOLDED); - mTarget.foldStateChanged(OPEN); - // No request display switch event (simulate very fast fold after unfold, even before - // the displays switched) - mTarget.foldStateChanged(FOLDED); - - requestDisplaySwitch(); - - assertTransitionNotRequested(); - } - - @Test - public void testDisplaySwitch_whenShellTransitionsNotEnabled_noTransition() { - givenAllAnimationsEnabled(); - givenShellTransitionsEnabled(false); - mTarget.foldStateChanged(FOLDED); - - mTarget.foldStateChanged(OPEN); - requestDisplaySwitch(); - - assertTransitionNotRequested(); - } - - @Test - public void testDisplaySwitch_whenAnimationsDisabled_noTransition() { - givenAllAnimationsEnabled(); - givenAnimationsEnabled(false); - mTarget.foldStateChanged(FOLDED); - - mTarget.foldStateChanged(OPEN); - requestDisplaySwitch(); - - assertTransitionNotRequested(); - } - - @Test - public void testDisplaySwitch_whenUnfoldAnimationDisabled_noTransition() { - givenAllAnimationsEnabled(); - givenUnfoldTransitionEnabled(false); - mTarget.foldStateChanged(FOLDED); - - mTarget.foldStateChanged(OPEN); - requestDisplaySwitch(); - - assertTransitionNotRequested(); - } - - @Test - public void testDisplaySwitchAfterUnfolding_otherCollectingTransition_collectsDisplaySwitch() { - givenAllAnimationsEnabled(); - mTarget.foldStateChanged(FOLDED); - - mTarget.foldStateChanged(OPEN); - requestDisplaySwitch(); - - // Collects to the current transition - assertTrue(mTransitionController.getCollectingTransition().mParticipants.contains( - mDisplayContent)); - } - - - @Test - public void testDisplaySwitch_whenNoContentInDisplayContent_noTransition() { - givenAllAnimationsEnabled(); - givenDisplayContentHasContent(false); - mTarget.foldStateChanged(FOLDED); - - mTarget.foldStateChanged(OPEN); - requestDisplaySwitch(); - - assertTransitionNotRequested(); - } - - private void assertTransitionRequested() { - assertNotNull(mPlayer.mLastRequest); - } - - private void assertTransitionNotRequested() { - assertNull(mPlayer.mLastRequest); - } - - private void requestDisplaySwitch() { - mTarget.requestDisplaySwitchTransitionIfNeeded( - mDisplayContent.getDisplayId(), - mDisplayContent.getBounds().width(), - mDisplayContent.getBounds().height(), - /* newDisplayWidth= */ 200, - /* newDisplayHeight= */ 250 - ); - } - - private void givenAllAnimationsEnabled() { - givenAnimationsEnabled(true); - givenUnfoldTransitionEnabled(true); - givenShellTransitionsEnabled(true); - givenDisplayContentHasContent(true); - } - - private void givenUnfoldTransitionEnabled(boolean enabled) { - when(mResources.getBoolean(config_unfoldTransitionEnabled)).thenReturn(enabled); - } - - private void givenAnimationsEnabled(boolean enabled) { - ValueAnimator.setDurationScale(enabled ? 1.0f : 0.0f); - } - - private void givenShellTransitionsEnabled(boolean enabled) { - if (enabled) { - mTransitionController.registerTransitionPlayer(mPlayer, null /* proc */); - } else { - mTransitionController.unregisterTransitionPlayer(mPlayer); - } - } - - private void givenDisplayContentHasContent(boolean hasContent) { - when(mDisplayContent.getLastHasContent()).thenReturn(hasContent); - } -} diff --git a/services/tests/wmtests/src/com/android/server/wm/TaskFragmentTest.java b/services/tests/wmtests/src/com/android/server/wm/TaskFragmentTest.java index 3c247a03d744..6be1af2c143f 100644 --- a/services/tests/wmtests/src/com/android/server/wm/TaskFragmentTest.java +++ b/services/tests/wmtests/src/com/android/server/wm/TaskFragmentTest.java @@ -995,16 +995,14 @@ public class TaskFragmentTest extends WindowTestsBase { // The focus should change. assertEquals(winLeftTop, mDisplayContent.mCurrentFocus); - if (Flags.embeddedActivityBackNavFlag()) { - // Move focus if the adjacent activity is more recently active. - doReturn(1L).when(appLeftTop).getLastWindowCreateTime(); - doReturn(2L).when(appRightTop).getLastWindowCreateTime(); - assertTrue(mWm.moveFocusToAdjacentEmbeddedWindow(winLeftTop)); - - // Do not move the focus if the adjacent activity is less recently active. - doReturn(3L).when(appLeftTop).getLastWindowCreateTime(); - assertFalse(mWm.moveFocusToAdjacentEmbeddedWindow(winLeftTop)); - } + // Move focus if the adjacent activity is more recently active. + doReturn(1L).when(appLeftTop).getLastWindowCreateTime(); + doReturn(2L).when(appRightTop).getLastWindowCreateTime(); + assertTrue(mWm.moveFocusToAdjacentEmbeddedWindow(winLeftTop)); + + // Do not move the focus if the adjacent activity is less recently active. + doReturn(3L).when(appLeftTop).getLastWindowCreateTime(); + assertFalse(mWm.moveFocusToAdjacentEmbeddedWindow(winLeftTop)); } @Test diff --git a/services/tests/wmtests/src/com/android/server/wm/TransitionTests.java b/services/tests/wmtests/src/com/android/server/wm/TransitionTests.java index 720457e24370..49e349caa379 100644 --- a/services/tests/wmtests/src/com/android/server/wm/TransitionTests.java +++ b/services/tests/wmtests/src/com/android/server/wm/TransitionTests.java @@ -2021,7 +2021,7 @@ public class TransitionTests extends WindowTestsBase { @EnableFlags(Flags.FLAG_MOVE_ANIMATION_OPTIONS_TO_CHANGE) @Test - public void testOverrideAnimationOptionsToInfoIfNecessary_nonCustomAnimOptions() { + public void testOverrideAnimationOptionsToInfoIfNecessary_fromStyleAnimOptions() { initializeOverrideAnimationOptionsTest(); TransitionInfo.AnimationOptions options = TransitionInfo.AnimationOptions .makeCommonAnimOptions("testPackage"); @@ -2047,6 +2047,32 @@ public class TransitionTests extends WindowTestsBase { @EnableFlags(Flags.FLAG_MOVE_ANIMATION_OPTIONS_TO_CHANGE) @Test + public void testOverrideAnimationOptionsToInfoIfNecessary_sceneAnimOptions() { + initializeOverrideAnimationOptionsTest(); + TransitionInfo.AnimationOptions options = TransitionInfo.AnimationOptions + .makeSceneTransitionAnimOptions(); + mTransition.setOverrideAnimation(options, null /* startCallback */, + null /* finishCallback */); + + mTransition.overrideAnimationOptionsToInfoIfNecessary(mInfo); + + final TransitionInfo.Change displayChange = mInfo.getChanges().get(0); + final TransitionInfo.Change taskChange = mInfo.getChanges().get(1); + final TransitionInfo.Change embeddedTfChange = mInfo.getChanges().get(2); + final TransitionInfo.Change activityChange = mInfo.getChanges().get(3); + + assertNull("Display change's AnimationOptions must not be overridden.", + displayChange.getAnimationOptions()); + assertEquals("Task change's AnimationOptions must be overridden.", + options, taskChange.getAnimationOptions()); + assertNull("Embedded TF change's AnimationOptions must not be overridden.", + embeddedTfChange.getAnimationOptions()); + assertEquals("Activity change's AnimationOptions must be overridden.", + options, activityChange.getAnimationOptions()); + } + + @EnableFlags(Flags.FLAG_MOVE_ANIMATION_OPTIONS_TO_CHANGE) + @Test public void testOverrideAnimationOptionsToInfoIfNecessary_crossProfileAnimOptions() { initializeOverrideAnimationOptionsTest(); TransitionInfo.AnimationOptions options = TransitionInfo.AnimationOptions diff --git a/tests/Input/src/com/android/test/input/InputEventAssignerTest.kt b/tests/Input/src/com/android/test/input/InputEventAssignerTest.kt index c1a86b3a2dac..015e188fc98e 100644 --- a/tests/Input/src/com/android/test/input/InputEventAssignerTest.kt +++ b/tests/Input/src/com/android/test/input/InputEventAssignerTest.kt @@ -18,12 +18,20 @@ package com.android.test.input import android.view.InputDevice.SOURCE_MOUSE import android.view.InputDevice.SOURCE_TOUCHSCREEN +import android.view.InputDevice.SOURCE_STYLUS +import android.view.InputDevice.SOURCE_TOUCHPAD + import android.view.InputEventAssigner import android.view.KeyEvent import android.view.MotionEvent import org.junit.Assert.assertEquals import org.junit.Test +sealed class StreamEvent +private data object Vsync : StreamEvent() +data class MotionEventData(val action: Int, val source: Int, val id: Int, val expectedId: Int) : + StreamEvent() + /** * Create a MotionEvent with the provided action, eventTime, and source */ @@ -49,64 +57,164 @@ private fun createKeyEvent(action: Int, eventTime: Long): KeyEvent { return KeyEvent(eventTime, eventTime, action, code, repeat) } +/** + * Check that the correct eventIds are assigned in a stream. The stream consists of motion + * events or vsync (processed frame) + * Each streamEvent should have unique ids when writing tests + * The test passes even if two events get assigned the same eventId, since the mapping is + * streamEventId -> motionEventId and streamEvents have unique ids + */ +private fun checkEventStream(vararg streamEvents: StreamEvent) { + val assigner = InputEventAssigner() + var eventTime = 10L + // Maps MotionEventData.id to MotionEvent.id + // We can't control the event id of the generated motion events but for testing it's easier + // to label the events with a custom id for readability + val eventIdMap: HashMap<Int, Int> = HashMap() + for (streamEvent in streamEvents) { + when (streamEvent) { + is MotionEventData -> { + val event = createMotionEvent(streamEvent.action, eventTime, streamEvent.source) + eventIdMap[streamEvent.id] = event.id + val eventId = assigner.processEvent(event) + assertEquals(eventIdMap[streamEvent.expectedId], eventId) + } + is Vsync -> assigner.notifyFrameProcessed() + } + eventTime += 1 + } +} + class InputEventAssignerTest { companion object { private const val TAG = "InputEventAssignerTest" } /** - * A single MOVE event should be assigned to the next available frame. + * A single event should be assigned to the next available frame. */ @Test - fun testTouchGesture() { - val assigner = InputEventAssigner() - val event = createMotionEvent(MotionEvent.ACTION_MOVE, 10, SOURCE_TOUCHSCREEN) - val eventId = assigner.processEvent(event) - assertEquals(event.id, eventId) + fun testTouchMove() { + checkEventStream( + MotionEventData(MotionEvent.ACTION_MOVE, SOURCE_TOUCHSCREEN, id = 1, expectedId = 1) + ) + } + + @Test + fun testMouseMove() { + checkEventStream( + MotionEventData(MotionEvent.ACTION_MOVE, SOURCE_MOUSE, id = 1, expectedId = 1) + ) + } + + @Test + fun testMouseScroll() { + checkEventStream( + MotionEventData(MotionEvent.ACTION_SCROLL, SOURCE_MOUSE, id = 1, expectedId = 1) + ) + } + + @Test + fun testStylusMove() { + checkEventStream( + MotionEventData(MotionEvent.ACTION_MOVE, SOURCE_STYLUS, id = 1, expectedId = 1) + ) + } + + @Test + fun testStylusHover() { + checkEventStream( + MotionEventData(MotionEvent.ACTION_HOVER_MOVE, SOURCE_STYLUS, id = 1, expectedId = 1) + ) + } + + @Test + fun testTouchpadMove() { + checkEventStream( + MotionEventData(MotionEvent.ACTION_MOVE, SOURCE_STYLUS, id = 1, expectedId = 1) + ) } /** - * DOWN event should be used until a vsync comes in. After vsync, the latest event should be - * produced. + * Test that before a VSYNC the event id generated by input event assigner for move events is + * the id of the down event. Move events coming after a VSYNC should be assigned their own event + * id */ + private fun testDownAndMove(source: Int) { + checkEventStream( + MotionEventData(MotionEvent.ACTION_DOWN, source, id = 1, expectedId = 1), + MotionEventData(MotionEvent.ACTION_MOVE, source, id = 2, expectedId = 1), + Vsync, + MotionEventData(MotionEvent.ACTION_MOVE, source, id = 4, expectedId = 4) + ) + } + @Test - fun testTouchDownWithMove() { - val assigner = InputEventAssigner() - val down = createMotionEvent(MotionEvent.ACTION_DOWN, 10, SOURCE_TOUCHSCREEN) - val move1 = createMotionEvent(MotionEvent.ACTION_MOVE, 12, SOURCE_TOUCHSCREEN) - val move2 = createMotionEvent(MotionEvent.ACTION_MOVE, 13, SOURCE_TOUCHSCREEN) - val move3 = createMotionEvent(MotionEvent.ACTION_MOVE, 14, SOURCE_TOUCHSCREEN) - val move4 = createMotionEvent(MotionEvent.ACTION_MOVE, 15, SOURCE_TOUCHSCREEN) - var eventId = assigner.processEvent(down) - assertEquals(down.id, eventId) - eventId = assigner.processEvent(move1) - assertEquals(down.id, eventId) - eventId = assigner.processEvent(move2) - // Even though we already had 2 move events, there was no choreographer callback yet. - // Therefore, we should still get the id of the down event - assertEquals(down.id, eventId) + fun testTouchDownAndMove() { + testDownAndMove(SOURCE_TOUCHSCREEN) + } - // Now send CALLBACK_INPUT to the assigner. It should provide the latest motion event - assigner.notifyFrameProcessed() - eventId = assigner.processEvent(move3) - assertEquals(move3.id, eventId) - eventId = assigner.processEvent(move4) - assertEquals(move4.id, eventId) + @Test + fun testMouseDownAndMove() { + testDownAndMove(SOURCE_MOUSE) + } + + @Test + fun testStylusDownAndMove() { + testDownAndMove(SOURCE_STYLUS) + } + + @Test + fun testTouchpadDownAndMove() { + testDownAndMove(SOURCE_TOUCHPAD) } /** - * Similar to the above test, but with SOURCE_MOUSE. Since we don't have down latency - * concept for non-touchscreens, the latest input event will be used. + * After an up event, motion events should be assigned their own event id */ @Test - fun testMouseDownWithMove() { - val assigner = InputEventAssigner() - val down = createMotionEvent(MotionEvent.ACTION_DOWN, 10, SOURCE_MOUSE) - val move1 = createMotionEvent(MotionEvent.ACTION_MOVE, 12, SOURCE_MOUSE) - var eventId = assigner.processEvent(down) - assertEquals(down.id, eventId) - eventId = assigner.processEvent(move1) - assertEquals(move1.id, eventId) + fun testMouseDownUpAndScroll() { + checkEventStream( + MotionEventData(MotionEvent.ACTION_DOWN, SOURCE_MOUSE, id = 1, expectedId = 1), + MotionEventData(MotionEvent.ACTION_UP, SOURCE_MOUSE, id = 2, expectedId = 2), + MotionEventData(MotionEvent.ACTION_SCROLL, SOURCE_MOUSE, id = 3, expectedId = 3) + ) + } + + /** + * After an up event, motion events should be assigned their own event id + */ + @Test + fun testStylusDownUpAndHover() { + checkEventStream( + MotionEventData(MotionEvent.ACTION_DOWN, SOURCE_STYLUS, id = 1, expectedId = 1), + MotionEventData(MotionEvent.ACTION_UP, SOURCE_STYLUS, id = 2, expectedId = 2), + MotionEventData(MotionEvent.ACTION_HOVER_ENTER, SOURCE_STYLUS, id = 3, expectedId = 3) + ) + } + + /** + * After a cancel event, motion events should be assigned their own event id + */ + @Test + fun testMouseDownCancelAndScroll() { + checkEventStream( + MotionEventData(MotionEvent.ACTION_DOWN, SOURCE_MOUSE, id = 1, expectedId = 1), + MotionEventData(MotionEvent.ACTION_CANCEL, SOURCE_MOUSE, id = 2, expectedId = 2), + MotionEventData(MotionEvent.ACTION_SCROLL, SOURCE_MOUSE, id = 3, expectedId = 3) + ) + } + + /** + * After a cancel event, motion events should be assigned their own event id + */ + @Test + fun testStylusDownCancelAndHover() { + checkEventStream( + MotionEventData(MotionEvent.ACTION_DOWN, SOURCE_STYLUS, id = 1, expectedId = 1), + MotionEventData(MotionEvent.ACTION_CANCEL, SOURCE_STYLUS, id = 2, expectedId = 2), + MotionEventData(MotionEvent.ACTION_HOVER_ENTER, SOURCE_STYLUS, id = 3, expectedId = 3) + ) } /** diff --git a/wifi/wifi.aconfig b/wifi/wifi.aconfig index f7162f6b7746..5a214b78e35e 100644 --- a/wifi/wifi.aconfig +++ b/wifi/wifi.aconfig @@ -35,3 +35,14 @@ flag { purpose: PURPOSE_BUGFIX } } + +flag { + name: "hotspot_network_connecting_state_for_details_page" + namespace: "wifi" + description: "Update getConnectedState in HotspotNetworkEntry so that details page displays correctly." + bug: "321096462" + is_fixed_read_only: true + metadata { + purpose: PURPOSE_BUGFIX + } +} |